package com.ruoyi.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.file.ImageUtils;
import com.ruoyi.project.domain.entity.*;
import com.ruoyi.project.domain.query.*;
import com.ruoyi.project.mapper.ProjectMapper;
import com.ruoyi.project.mapper.ProjectParticipanMapper;
import com.ruoyi.project.mapper.ProjectPhaseMapper;
import com.ruoyi.project.mapper.ProjectWarrantyMapper;
import com.ruoyi.project.service.*;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

    @Resource
    private ProjectMapper projectMapper;

    @Resource
    private ProjectParticipanMapper projectParticipanMapper;

    @Resource
    private ProjectPhaseMapper projectPhaseMapper;

    @Resource
    private IProjectParticipanService participanService;

    @Resource
    private IProjectAttachmentService fileService;

    @Resource
    private IProjectImplementService implementService;

    @Resource
    private IProjectPayService payService;

    @Resource
    private IProjectAccountingService accountingService;

    @Resource
    private IProjectWarrantyService warrantyService;

    @Resource
    private IProjectPhaseService phaseService;

    @Resource
    private ISysDictDataService dictService;

    @Autowired
    private ISysDictDataService dictDataService;

    @Resource
    IPhaseDictionaryService phaseDictionaryService;

    @Resource
    private IProjectAllocationDetailService detailService;

    @Resource
    private IProjectService projectService;

    @Resource
    IProjectFeeService feeService;

    @Resource
    IProjectFinanceService financeService;

    @Resource
    private IProjectAllocationService allocationService;

    @Resource
    private IProjectAllocationDetailService allocationDetailService;

    @Resource
    IProjectCostingService costingService;

    @Resource
    IProjectSaleService saleService;

    @Resource
    ISysUserService userService;

    @Resource
    IProjectMatchingService matchingService;

    @Autowired
    private RedisCache redisCache;

    public static final String HCXX = "HCXX"; // 固定前缀
    public static final String SDGC = "SDGC"; // 固定前缀
    public static final String YSZH = "YSZH"; // 固定前缀
    @Autowired
    private ProjectWarrantyMapper projectWarrantyMapper;
    private ProjectWarrantyServiceImpl projectWarrantyServiceImpl;

    //分页
    @Override
    public TableDataInfo getPage(ProjectQuery query) {
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            System.out.println("当前用户有admin角色权限");
        } else { //查询自己创建的或参与的
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);
        }
        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> list = projectMapper.getList(query);
        for (Project project : list) {
            setOprator(project);
            setCurentPeople(project);
            setWarranty(project);
        }
        //组装数据
        return new TableDataInfo(list, page.getTotal());
    }

    @Override
    public TableDataInfo getSaleProjectPage(ProjectQuery query) {
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            System.out.println("当前用户有admin角色权限");
        } else { //查询自己创建的或参与的
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);
        }

        List<String> adminList = new ArrayList<>();
        //如果选了销售负责人
        if (query.getSaleRole() != null) {
            System.out.println("当前用户有admin角色权限");//管理员看全部？
            List<String> saleRoleProjectNo = getSaleRoleProjectNo(query);
            adminList.addAll(saleRoleProjectNo);
            adminList.add("0");
            query.setProjectList(adminList);
        }

        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());

        //只查询销售项目
        query.setSaleProject("2");

        List<Project> list = projectMapper.getSaleListPage(query);
        //组装数据
        return new TableDataInfo(list, page.getTotal());
    }


    @Override
    public Map<String, BigDecimal> getCompeleteMoney(ProjectQuery query) {


        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            System.out.println("当前用户有admin角色权限");
        } else { //查询自己创建的或参与的
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);
        }

        Map<String, BigDecimal> map = new HashMap<>();
        List<Project> list = projectMapper.getList(query);
        for (Project project : list) {
            Date acceptTime = project.getAcceptTime();
            BigDecimal settlementAmount = project.getSettlementAmount();
        }

        // 用于格式化日期，提取年份
        SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");

        for (Project project : list) {
            Date acceptTime = project.getAcceptTime();
            BigDecimal settlementAmount = project.getSettlementAmount();

            // 安全性检查：确保日期和金额不为null
            if (acceptTime != null && settlementAmount != null) {
                // 将日期格式化为 "yyyy" 格式的字符串（即年份）
                String year = yearFormat.format(acceptTime);
                // 将当前项目的结算金额累加到对应年份的总金额中
                map.merge(year, settlementAmount, BigDecimal::add);
            }
        }
        //组装数据
        return map;
    }


    public void setWarranty(Project project) {
        LambdaQueryWrapper<ProjectWarranty> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ProjectWarranty::getProjectNo, project.getProjectNo());
        List<ProjectWarranty> warrantyList = warrantyService.list(wrapper);
        if (warrantyList != null && warrantyList.size() > 0) {
            Date startDate = warrantyList.get(0).getStartDate();
            project.setWarrantyStartDate(startDate);
            Date endDate = warrantyList.get(0).getEndDate();
            project.setWarrantyEndDate(endDate);
        }


    }

    //分页
    @Override
    public TableDataInfo appListProject(ProjectQuery query) {
        query.setStatus("1");
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            System.out.println("当前用户有admin角色权限");

            LambdaQueryWrapper<ProjectPhase> phaseWrapper = Wrappers.lambdaQuery();
            phaseWrapper.select(ProjectPhase::getProjectNo); // 只选择 projectNo 字段
            phaseWrapper.eq(ProjectPhase::getStatus, "1");
            phaseWrapper.and(wrapper -> wrapper.in(ProjectPhase::getPhaseId, Arrays.asList("2", "3", "4")));

// 使用 selectObjs 获取单列字段值
            List<String> projectNoList = phaseService.listObjs(phaseWrapper, Object::toString);
            projectNoList.add("0");
            query.setProjectList(projectNoList);

        } else { //查询自己创建的或参与的
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in

            LambdaQueryWrapper<ProjectPhase> phaseWrapper = Wrappers.lambdaQuery();
            phaseWrapper.in(ProjectPhase::getProjectNo, currentUserJoinProject);
            phaseWrapper.eq(ProjectPhase::getStatus, "1");
            phaseWrapper.and(wrapper -> wrapper.in(ProjectPhase::getPhaseId, Arrays.asList("2", "3", "4")));
            List<ProjectPhase> projectPhaseList = phaseService.list(phaseWrapper);


            // 假设 ProjectPhase 类中有一个 getProjectNo() 方法
            List<String> projectNoFromPhaseList = projectPhaseList.stream()
                    .map(ProjectPhase::getProjectNo)
                    .distinct()
                    .collect(Collectors.toList());

            // 取交集
            List<String> intersectedProjects = currentUserJoinProject.stream()
                    .filter(projectNoFromPhaseList::contains)
                    .collect(Collectors.toList());
            intersectedProjects.add("0");
            query.setProjectList(intersectedProjects);
        }
        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> list = projectMapper.getList(query);
        for (Project project : list) {
            setOprator(project);
            setCurentPeople(project);
        }
        //组装数据
        return new TableDataInfo(list, page.getTotal());
    }


    //分页
    @Override
    public TableDataInfo allocations(ProjectQuery query) {
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            System.out.println("当前用户有admin角色权限");
        } else { //查询自己创建的或参与的
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);
        }
        //先把核算已完成的项目全部查询出来 遍历 判断是否已经发放完成


        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> list = projectMapper.getList(query);
        for (Project project : list) {
            setOprator(project);
            setCurentPeople(project);
        }
        return new TableDataInfo(list, page.getTotal());
    }


    //新增
    @Override
    public Project addInfo(Project project) {
        checkProject(project);
        //生成唯一编号
        String prefix = CreateProjectNo.PREFIX;
        String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        String projectNo = CreateProjectNo.generateNextCode(projectMapper.findMaxProjectNo(prefix + yearMonth));
        project.setProjectNo(projectNo);

        //插入用户id和部门id 为了使用数据权限
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        project.setUserId(user.getUserId());
        project.setDeptId(user.getDeptId());
        project.setCreateDept(user.getDeptId());
        project.setCreateUserName(user.getNickName());

        //保存参与人员信息
        if (CollectionUtils.isNotEmpty(project.getParticipanList())) {
            project.getParticipanList().forEach(participant -> {
                participant.setOperator(SecurityUtils.getLoginUser().getUser().getNickName());
                participant.setProjectNo(projectNo);
                projectParticipanMapper.insert(participant);
            });
        }

        //插入阶段信息 立项阶段 写死 id 1

        PhaseDictionary config = phaseDictionaryService.getById(1);
        String phaseName = config.getPhaseName();

        ProjectPhase phase = new ProjectPhase();
        phase.setPhaseId("1");//立项阶段
        phase.setProjectNo(projectNo);
        phase.setPhaseName(phaseName);
        phase.setStatus("1");//1为进行中 2为已提交到下一步
        phase.setAudit(new ArrayList<Integer>());
        phase.setOperator(loginUser.getUser().getNickName());
        projectPhaseMapper.insert(phase);

        //如果选择了归属公司 生成归属公司的编码
        if (StringUtils.isNotEmpty(project.getCompanyType())) {
            String companyPrefix;
            if ("1".equals(project.getCompanyType())) {
                companyPrefix = HCXX;
            } else if ("2".equals(project.getCompanyType())) {
                companyPrefix = SDGC;
            } else if ("3".equals(project.getCompanyType())) {
                companyPrefix = YSZH;
            } else {
                throw new IllegalArgumentException("归属公司类型有误");
            }
            String maxCodeByPrefix = this.findMaxCodeByPrefix(companyPrefix);
            String resultCode = generateCompanyCode(maxCodeByPrefix, companyPrefix);
            project.setCompanyNo(resultCode);
        }


        boolean save = this.save(project);

        return project;
    }

    @Override
    public Boolean updateInfo(Project project) {
        setCW(project);
        checkHouseProject(project);
        checkProject(project);
        ProjectParticipanQuery query = new ProjectParticipanQuery();
        query.setProjectNo(project.getProjectNo());
        if (CollectionUtils.isNotEmpty(project.getParticipanList())) {
            project.getParticipanList().forEach(participant -> {
//                participant.setOperator(SecurityUtils.getLoginUser().getUser().getNickName());
                participant.setProjectNo(project.getProjectNo());
                if (StringUtils.isNotNull(participant.getId())) {//修改的
                    projectParticipanMapper.updateById(participant);
                } else {//新增的
                    projectParticipanMapper.insert(participant);
                }
            });
        }

        if (StringUtils.isNotEmpty(project.getCompanyType())) {
            // 根据公司类型获取前缀（统一方法管理映射）
            String companyPrefix = getPrefixByCompanyType(project.getCompanyType());

            // 校验项目是否存在
            Project infoById = this.getInfoById(project.getProjectNo());
            if (infoById == null) {
                throw new IllegalArgumentException("项目不存在");
            }

            if (StringUtils.isNotEmpty(project.getCompanyNo())) {
                // 检查公司类型是否变更
                if (!infoById.getCompanyType().equals(project.getCompanyType())) {
                    // 类型变更，强制生成新编码
                    String maxCode = this.findMaxCodeByPrefix(companyPrefix);
                    String newCode = generateCompanyCode(maxCode, companyPrefix);
                    project.setCompanyNo(newCode);
                } else {
                    // 类型未变更，比较编号是否相同
                    if (StringUtils.isNotEmpty(infoById.getCompanyNo())) {
                        if (!infoById.getCompanyNo().equals(project.getCompanyNo())) {
                            // 编号不同，重新生成
                            String maxCode = this.findMaxCodeByPrefix(companyPrefix);
                            String newCode = generateCompanyCode(maxCode, companyPrefix);
                            project.setCompanyNo(newCode);
                        }
                    }
                }
            } else {
                // 空的情况下生成新编码
                String maxCode = this.findMaxCodeByPrefix(companyPrefix);
                String newCode = generateCompanyCode(maxCode, companyPrefix);
                project.setCompanyNo(newCode);
            }
        }
        return this.updateById(project);
    }

    @Override
    public Project addSaleProject(Project project) {
        //必须关联管家婆项目
        if (StringUtils.isEmpty(project.getHousekeeperProject())) {
            throw new RuntimeException("必须关联管家婆项目!");
        }

        checkProject(project);
        //生成唯一编号
        String prefix = CreateSaleProjectNo.PREFIX;
        String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        String projectNo = CreateSaleProjectNo.generateNextCode(projectMapper.findMaxProjectNo(prefix + yearMonth));
        project.setProjectNo(projectNo);

        //插入用户id和部门id 为了使用数据权限
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        project.setUserId(user.getUserId());
        project.setDeptId(user.getDeptId());
        project.setCreateDept(user.getDeptId());
        project.setCreateUserName(user.getNickName());

        //保存参与人员信息
        if (CollectionUtils.isNotEmpty(project.getParticipanList())) {
            project.getParticipanList().forEach(participant -> {
                participant.setOperator(SecurityUtils.getLoginUser().getUser().getNickName());
                participant.setProjectNo(projectNo);
                projectParticipanMapper.insert(participant);
            });
        }

        //如果选择了归属公司 生成归属公司的编码
        if (StringUtils.isNotEmpty(project.getCompanyType())) {
            String companyPrefix;
            if ("1".equals(project.getCompanyType())) {
                companyPrefix = HCXX;
            } else if ("2".equals(project.getCompanyType())) {
                companyPrefix = SDGC;
            } else if ("3".equals(project.getCompanyType())) {
                companyPrefix = YSZH;
            } else {
                throw new IllegalArgumentException("归属公司类型有误");
            }
            String maxCodeByPrefix = this.findMaxCodeByPrefix(companyPrefix);
            String resultCode = generateCompanyCode(maxCodeByPrefix, companyPrefix);
            project.setCompanyNo(resultCode);
        }
        //标记为销售项目
        project.setSaleProject("2");

        boolean save = this.save(project);

        if (save) {
            //设置一下财务
            //setCW(project);
        }

        return project;
    }


    public boolean checkSaleMoney(Project project) {
        //归档校验有无收齐款
        BigDecimal amount = project.getSettlementAmount() != null ? project.getSettlementAmount() : project.getContractAmount();
        String housekeeperProject = project.getHousekeeperProject();

        ProjectFeeQuery projectFeeQuery = new ProjectFeeQuery();
        projectFeeQuery.setHousekeeperProject(housekeeperProject);
        List<ProjectFee> feeList = feeService.getReceiveFee(projectFeeQuery);
        BigDecimal feeAmount = BigDecimal.ZERO;
        for (ProjectFee projectFee : feeList) {
            feeAmount = feeAmount.add(projectFee.getTotal());
        }

        //比较结算金额和总收款 相等则返回true
        // 比较收款金额是否小于等于结算金额
        if (feeAmount != null && amount != null) {
            if (feeAmount.compareTo(amount) < 0) {
                return false;
            }
        }
        return true;
    }

    @Override
    public Boolean updateSaleProject(Project project) {

        //归档校验有无收齐款
        if ("2".equals(project.getSaleCom())) {
            BigDecimal amount = project.getSettlementAmount() != null ? project.getSettlementAmount() : project.getContractAmount();
            String housekeeperProject = project.getHousekeeperProject();

            ProjectFeeQuery projectFeeQuery = new ProjectFeeQuery();
            projectFeeQuery.setHousekeeperProject(housekeeperProject);
            List<ProjectFee> feeList = feeService.getReceiveFee(projectFeeQuery);
            BigDecimal feeAmount = BigDecimal.ZERO;
            for (ProjectFee projectFee : feeList) {
                feeAmount = feeAmount.add(projectFee.getTotal());
            }

            //比较结算金额和总收款 相等则返回true
            // 比较收款金额是否小于等于结算金额
            if (feeAmount != null && amount != null) {
                if (feeAmount.compareTo(amount) < 0) {
                    throw new RuntimeException("应收款未收齐,不允许归档!");
                }
            }

        }


        checkHouseProject(project);
        checkProject(project);
        ProjectParticipanQuery query = new ProjectParticipanQuery();
        query.setProjectNo(project.getProjectNo());
        if (CollectionUtils.isNotEmpty(project.getParticipanList())) {
            project.getParticipanList().forEach(participant -> {
                participant.setProjectNo(project.getProjectNo());
                if (StringUtils.isNotNull(participant.getId())) {//修改的
                    projectParticipanMapper.updateById(participant);
                } else {//新增的
                    projectParticipanMapper.insert(participant);
                }
            });
        }

        if (StringUtils.isNotEmpty(project.getCompanyType())) {
            // 根据公司类型获取前缀（统一方法管理映射）
            String companyPrefix = getPrefixByCompanyType(project.getCompanyType());

            // 校验项目是否存在
            Project infoById = this.getInfoById(project.getProjectNo());
            if (infoById == null) {
                throw new IllegalArgumentException("项目不存在");
            }

            if (StringUtils.isNotEmpty(project.getCompanyNo())) {
                // 检查公司类型是否变更
                if (!infoById.getCompanyType().equals(project.getCompanyType())) {
                    // 类型变更，强制生成新编码
                    String maxCode = this.findMaxCodeByPrefix(companyPrefix);
                    String newCode = generateCompanyCode(maxCode, companyPrefix);
                    project.setCompanyNo(newCode);
                } else {
                    // 类型未变更，比较编号是否相同
                    if (StringUtils.isNotEmpty(infoById.getCompanyNo())) {
                        if (!infoById.getCompanyNo().equals(project.getCompanyNo())) {
                            // 编号不同，重新生成
                            String maxCode = this.findMaxCodeByPrefix(companyPrefix);
                            String newCode = generateCompanyCode(maxCode, companyPrefix);
                            project.setCompanyNo(newCode);
                        }
                    }
                }
            } else {
                // 空的情况下生成新编码
                String maxCode = this.findMaxCodeByPrefix(companyPrefix);
                String newCode = generateCompanyCode(maxCode, companyPrefix);
                project.setCompanyNo(newCode);
            }
        }
        return this.updateById(project);
    }


    //自动添加财务
    public void setCW(Project project) {
        String companyType = project.getCompanyType();
        if (StringUtils.isNotEmpty(companyType)) {
            SysDictData sysDictData = new SysDictData();
            if ("1".equals(companyType)) {
                sysDictData = dictService.selectDictDataById(158L);
            } else if ("2".equals(companyType)) {
                sysDictData = dictService.selectDictDataById(159L);
            } else if ("3".equals(companyType)) {
                sysDictData = dictService.selectDictDataById(160L);
            }

            if (sysDictData != null && StringUtils.isNotEmpty(sysDictData.getRemark())) {
                Long userID = Long.valueOf(sysDictData.getRemark());
                //查询参与人员信息
                LambdaQueryWrapper<ProjectParticipan> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ProjectParticipan::getProjectNo, project.getProjectNo());
                queryWrapper.eq(ProjectParticipan::getParticipantId, userID);
                queryWrapper.eq(ProjectParticipan::getPostId, 6L);
                List<ProjectParticipan> list = participanService.list(queryWrapper);
                //如果没添加
                if (!CollectionUtils.isNotEmpty(list)) {
                    SysUser sysUser = userService.selectUserById(userID);
                    ProjectParticipan person = new ProjectParticipan();
                    person.setProjectNo(project.getProjectNo());
                    person.setParticipantId(userID);
                    person.setPostId(6L);
                    person.setParticipanName(sysUser.getNickName());
                    person.setPostName("财务");
                    person.setPhaseId(Long.valueOf(project.getPhaseId()));
                    participanService.addInfo(person);
                }

            }

        }

    }

    public void checkProject(Project project) {
        //如果有管家婆项目 先校验有没有被其他项目关联过
        if (project != null && StringUtils.hasText(project.getHousekeeperProject())) {
            String housekeeperProject = project.getHousekeeperProject();
            String projectId = project.getProjectNo(); // 当前项目的 ID，用于编辑时排除自己

            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getHousekeeperProject, housekeeperProject);

            // 如果是编辑操作，排除当前项目自身
            if (projectId != null) {
                queryWrapper.ne(Project::getProjectNo, projectId);
            }

            // 使用 count 判断是否存在记录（性能更优）
            int count = projectService.count(queryWrapper);
            if (count > 0) {
                // 如果需要显示关联的项目名，再查询一次
                Project existing = projectService.getOne(queryWrapper);
                throw new RuntimeException("该管家婆项目已被 " + existing.getProjectName() + " 关联,不可再次选择");
            }
        }

        //检测项目名称是否有重复
        String projectId = project.getProjectNo(); // 当前项目的 ID，用于编辑时排除自己

        LambdaQueryWrapper<Project> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Project::getProjectName, project.getProjectName());

        // 如果是编辑操作，排除当前项目自身
        if (projectId != null) {
            wrapper.ne(Project::getProjectNo, projectId);
        }

        // 使用 count 判断是否存在记录（性能更优）
        int count = projectService.count(wrapper);
        if (count > 0) {
            throw new RuntimeException("项目名称重复！");
        }

    }

    public void checkHouseProject(Project project) {
        if (project == null || !StringUtils.hasText(project.getHousekeeperProject())) {
            return;
        }

        String projectId = project.getProjectNo();
        String newHousekeeperProject = project.getHousekeeperProject();

        Project oldProject = projectService.getById(projectId);
        if (oldProject == null) {
            return; // 或抛出异常，视业务需求而定
        }

        String oldHousekeeperProject = oldProject.getHousekeeperProject();

        if (newHousekeeperProject.equals(oldHousekeeperProject)) {
//            return; // 没有变化，无需处理
        }

        // 删除旧数据并生成新数据
        payService.deleteByProjectNo(projectId);
        projectService.createPay(projectId);
    }

    @Override
    public Boolean deleteInfo(String id) {
        //        projectPhaseMapper.deleteById(id);
        //删除相关表的信息?
        //1.删除参与人员信息
        LambdaUpdateWrapper<ProjectParticipan> personDeleteWrapper = Wrappers.lambdaUpdate();
        personDeleteWrapper.eq(ProjectParticipan::getProjectNo, id);
        participanService.remove(personDeleteWrapper);

        //2.删除附件信息
        LambdaUpdateWrapper<ProjectAttachment> fileDeleteWrapper = Wrappers.lambdaUpdate();
        fileDeleteWrapper.eq(ProjectAttachment::getProjectNo, id);
        fileService.remove(fileDeleteWrapper);


        //3.删除付款信息
        LambdaUpdateWrapper<ProjectPay> payDeleteWrapper = Wrappers.lambdaUpdate();
        payDeleteWrapper.eq(ProjectPay::getProjectNo, id);
        payService.remove(payDeleteWrapper);

        //4.删除实施日志
        LambdaUpdateWrapper<ProjectImplement> implementDeleteWrapper = Wrappers.lambdaUpdate();
        implementDeleteWrapper.eq(ProjectImplement::getProjectNo, id);
        implementService.remove(implementDeleteWrapper);

        //5.删除核算信息
        LambdaUpdateWrapper<ProjectAccounting> accountingDeleteWrapper = Wrappers.lambdaUpdate();
        accountingDeleteWrapper.eq(ProjectAccounting::getProjectNo, id);
        accountingService.remove(accountingDeleteWrapper);

        //6.删除质保信息
        LambdaUpdateWrapper<ProjectWarranty> warrantyDeleteWrapper = Wrappers.lambdaUpdate();
        warrantyDeleteWrapper.eq(ProjectWarranty::getProjectNo, id);
        warrantyService.remove(warrantyDeleteWrapper);

        //7.删除绩效分配信息
        LambdaUpdateWrapper<ProjectAllocation> allocationDeleteWrapper = Wrappers.lambdaUpdate();
        allocationDeleteWrapper.eq(ProjectAllocation::getProjectNo, id);
        allocationService.remove(allocationDeleteWrapper);

        LambdaUpdateWrapper<AllocationDetail> allocationDetailDeleteWrapper = Wrappers.lambdaUpdate();
        allocationDetailDeleteWrapper.eq(AllocationDetail::getProjectNo, id);
        allocationDetailService.remove(allocationDetailDeleteWrapper);

        //8.删除正式清单信息
        LambdaUpdateWrapper<ProjectCosting> costingDeleteWrapper = Wrappers.lambdaUpdate();
        costingDeleteWrapper.eq(ProjectCosting::getProjectNo, id);
        costingService.remove(costingDeleteWrapper);

        //9.删除阶段信息
        LambdaUpdateWrapper<ProjectPhase> phaseDeleteWrapper = Wrappers.lambdaUpdate();
        phaseDeleteWrapper.eq(ProjectPhase::getProjectNo, id);
        phaseService.remove(phaseDeleteWrapper);


        return this.removeById(id);
    }

    @Override
    public Project getInfoById(String id) {
        return this.getById(id);
    }


    @Override
    public TableDataInfo getAssistListPage(ProjectQuery query) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);
        query.setProjectType("4");
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {

            List<String> adminList = new ArrayList<>();
            //如果选了销售负责人
            if (query.getSaleRole() != null) {
                System.out.println("当前用户有admin角色权限");//管理员看全部？
                List<String> saleRoleProjectNo = getSaleRoleProjectNo(query);
                adminList.addAll(saleRoleProjectNo);
            } else {
                System.out.println("当前用户有admin角色权限");//管理员看全部？
                LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
                List<Project> list = projectMapper.selectList(queryWrapper);
                for (Project project : list) {
                    adminList.add(project.getProjectNo());
                }
            }

            adminList.add("0");
            query.setProjectList(adminList);
            Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
            List<Project> resultList = projectMapper.getList(query);
            for (Project project : resultList) {
                setOprator(project);
                setCurentPeople(project);
            }
            return new TableDataInfo(resultList, page.getTotal());
        } else {
            //
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            //我发起的
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            //我参与的
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);
            // 转 Set 去重
            Set<String> set = new LinkedHashSet<>(query.getProjectList()); // 保持顺序
            // 再转回 List
            List<String> uniqueList = new ArrayList<>(set);

            if (query.getSaleRole() != null) {
                List<String> saleRoleProjectNo = getSaleRoleProjectNo(query);

                // 将 saleRoleProjectNo 转成 Set，提升查找效率
                Set<String> allowedProjects = new HashSet<>(saleRoleProjectNo);
                // 遍历 uniqueList，只保留存在于 allowedProjects 中的项
                List<String> intersection = uniqueList.stream()
                        .filter(allowedProjects::contains)
                        .collect(Collectors.toList());
                query.setProjectList(intersection);

            } else {
                query.setProjectList(uniqueList);
            }
            Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
            System.out.println(page);
            List<Project> list = projectMapper.getList(query);
            for (Project project : list) {
                setOprator(project);
                setCurentPeople(project);
            }
            return new TableDataInfo(list, page.getTotal());
        }
    }

    @Override
    public TableDataInfo getMyJoinListPage(ProjectQuery query) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {

            List<String> adminList = new ArrayList<>();
            //如果选了销售负责人
            if (query.getSaleRole() != null) {
                System.out.println("当前用户有admin角色权限");//管理员看全部？
                List<String> saleRoleProjectNo = getSaleRoleProjectNo(query);
                adminList.addAll(saleRoleProjectNo);
            } else {
                System.out.println("当前用户有admin角色权限");//管理员看全部？
                LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
                List<Project> list = projectMapper.selectList(queryWrapper);
                for (Project project : list) {
                    adminList.add(project.getProjectNo());
                }
            }

            adminList.add("0");
            query.setProjectList(adminList);
            Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
            List<Project> resultList = projectMapper.getList(query);
            for (Project project : resultList) {
                setOprator(project);
                setCurentPeople(project);
            }
            return new TableDataInfo(resultList, page.getTotal());
        } else {
            //
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            //我发起的
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            //我参与的
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);
            // 转 Set 去重
            Set<String> set = new LinkedHashSet<>(query.getProjectList()); // 保持顺序
            // 再转回 List
            List<String> uniqueList = new ArrayList<>(set);

            if (query.getSaleRole() != null) {
                List<String> saleRoleProjectNo = getSaleRoleProjectNo(query);

                // 将 saleRoleProjectNo 转成 Set，提升查找效率
                Set<String> allowedProjects = new HashSet<>(saleRoleProjectNo);
                // 遍历 uniqueList，只保留存在于 allowedProjects 中的项
                List<String> intersection = uniqueList.stream()
                        .filter(allowedProjects::contains)
                        .collect(Collectors.toList());
                query.setProjectList(intersection);

            } else {
                query.setProjectList(uniqueList);
            }
            Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
            System.out.println(page);
            List<Project> list = projectMapper.getList(query);
            for (Project project : list) {
                setOprator(project);
                setCurentPeople(project);
            }
            return new TableDataInfo(list, page.getTotal());
        }


    }


    public List<String> getSaleRoleProjectNo(ProjectQuery query) {
        LambdaQueryWrapper<ProjectParticipan> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ProjectParticipan::getParticipantId, query.getSaleRole())
                .eq(ProjectParticipan::getPostId, 5L)
                .select(ProjectParticipan::getProjectNo); //  只查 projectNo 字段

        List<ProjectParticipan> list = participanService.list(queryWrapper);

        // 提取 projectNo 到 List<String>
        return list.stream()
                .map(ProjectParticipan::getProjectNo)
                .distinct() // 去重可选
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, BigDecimal> getMyJoinListCount(ProjectQuery query) {
        Map<String, BigDecimal> map = new HashMap<>();
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);
        BigDecimal contractAmountTotal = BigDecimal.ZERO;
        BigDecimal settlementAmountTotal = BigDecimal.ZERO;
        BigDecimal receivedTotal = BigDecimal.ZERO;
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            List<String> adminList = new ArrayList<>();
            if (query.getSaleRole() != null) {
                System.out.println("当前用户有admin角色权限");//管理员看全部？
                List<String> saleRoleProjectNo = getSaleRoleProjectNo(query);
                adminList.addAll(saleRoleProjectNo);
            } else {
                System.out.println("当前用户有admin角色权限");//管理员看全部？
                LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
                List<Project> list = projectMapper.selectList(queryWrapper);
                for (Project project : list) {
                    adminList.add(project.getProjectNo());
                }
            }

            adminList.add("0");
            query.setProjectList(adminList);
            List<Project> resultList = projectMapper.getList(query);

            // 1. 预收集所有需要查询的housekeeperProject
            Set<String> housekeeperProjects = resultList.stream()
                    .map(Project::getHousekeeperProject)
                    .filter(StringUtils::isNotEmpty)
                    .collect(Collectors.toSet());

            // 2. 批量查询所有相关费用数据（一次性数据库查询）
            Map<String, List<ProjectFee>> feeMap = Collections.emptyMap();
            if (!housekeeperProjects.isEmpty()) {
                LambdaQueryWrapper<ProjectFee> wrapper = new LambdaQueryWrapper<ProjectFee>()
                        .in(ProjectFee::getHousekeeperProject, housekeeperProjects)
                        .eq(ProjectFee::getUseType, "1")
                        .in(ProjectFee::getMainType, Arrays.asList("4")); // 包含冲红数据

                feeMap = feeService.list(wrapper)
                        .stream()
                        .collect(Collectors.groupingBy(ProjectFee::getHousekeeperProject));
            }


            // 3. 单次循环处理所有数据
            for (Project project : resultList) {
                // 累加合同金额
                if (project.getContractAmount() != null) {
                    contractAmountTotal = contractAmountTotal.add(project.getContractAmount());
                }

                // 累加结算金额
                if (project.getSettlementAmount() != null) {
                    settlementAmountTotal = settlementAmountTotal.add(project.getSettlementAmount());
                }

                // 处理实收金额（内存计算）
                if (StringUtils.isNotEmpty(project.getHousekeeperProject())) {
                    List<ProjectFee> fees = feeMap.getOrDefault(project.getHousekeeperProject(), Collections.emptyList());
                    for (ProjectFee fee : fees) {
                        if (fee.getTotal() != null) {
                            receivedTotal = receivedTotal.add(fee.getTotal());
                        }
                    }
                }
            }


            map.put("contractAmountTotal", contractAmountTotal);
            map.put("settlementAmountTotal", settlementAmountTotal);
            map.put("receivedTotal", receivedTotal);
            return map;
        } else {
            //
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            //我发起的
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            //我参与的
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);


        }

        // 转 Set 去重
        Set<String> set = new LinkedHashSet<>(query.getProjectList()); // 保持顺序
        // 再转回 List
        List<String> uniqueList = new ArrayList<>(set);

        if (query.getSaleRole() != null) {
            List<String> saleRoleProjectNo = getSaleRoleProjectNo(query);

            // 将 saleRoleProjectNo 转成 Set，提升查找效率
            Set<String> allowedProjects = new HashSet<>(saleRoleProjectNo);
            // 遍历 uniqueList，只保留存在于 allowedProjects 中的项
            List<String> intersection = uniqueList.stream()
                    .filter(allowedProjects::contains)
                    .collect(Collectors.toList());
            query.setProjectList(intersection);

        } else {
            query.setProjectList(uniqueList);
        }

        List<Project> list = projectMapper.getList(query);

        // 1. 预收集所有需要查询的housekeeperProject
        Set<String> housekeeperProjects = list.stream()
                .map(Project::getHousekeeperProject)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toSet());

// 2. 批量查询所有相关费用数据（一次性数据库查询）
        Map<String, List<ProjectFee>> feeMap = Collections.emptyMap();
        if (!housekeeperProjects.isEmpty()) {
            LambdaQueryWrapper<ProjectFee> wrapper = new LambdaQueryWrapper<ProjectFee>()
                    .in(ProjectFee::getHousekeeperProject, housekeeperProjects)
                    .eq(ProjectFee::getUseType, "1")
                    .in(ProjectFee::getMainType, Arrays.asList("4")); // 包含冲红数据

            feeMap = feeService.list(wrapper)
                    .stream()
                    .collect(Collectors.groupingBy(ProjectFee::getHousekeeperProject));
        }

// 3. 初始化统计变量

// 4. 单次循环处理所有数据
        for (Project project : list) {

            // 累加合同金额
            if (project.getContractAmount() != null) {
                contractAmountTotal = contractAmountTotal.add(project.getContractAmount());
            }

            // 累加结算金额
            if (project.getSettlementAmount() != null) {
                settlementAmountTotal = settlementAmountTotal.add(project.getSettlementAmount());
            }

            // 处理实收金额（内存计算）
            if (StringUtils.isNotEmpty(project.getHousekeeperProject())) {
                List<ProjectFee> fees = feeMap.getOrDefault(project.getHousekeeperProject(), Collections.emptyList());
                for (ProjectFee fee : fees) {
                    if (fee.getTotal() != null) {
                        receivedTotal = receivedTotal.add(fee.getTotal());
                    }
                }
            }
        }

        map.put("contractAmountTotal", contractAmountTotal);
        map.put("settlementAmountTotal", settlementAmountTotal);
        map.put("receivedTotal", receivedTotal);
        return map;
    }

    // 常量定义
    private static final BigDecimal TEN_THOUSAND = new BigDecimal("10000");

    @Override
    public List<DataView> getFirstPanelByYear(ProjectQuery query) {
        // 初始化统计变量：0=合同金额, 1=结算金额, 2=实收金额, 3=开票金额
        query.setFirst("1");//统计的是第一块的内容 只统计销售负责人和项目经理负责的项目
        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        List<DataView> cachedData = (List<DataView>) redisCache.redisTemplate.opsForValue().get(String.valueOf(userId) + "firstPanel" + String.valueOf(query.getYear()));
        if (cachedData != null && query.getRefresh().equals("1")) {
            return cachedData;
        }

        BigDecimal[] currentYearTotals = new BigDecimal[5];
        BigDecimal[] lastYearTotals = new BigDecimal[5];
        Arrays.fill(currentYearTotals, BigDecimal.ZERO);
        Arrays.fill(lastYearTotals, BigDecimal.ZERO);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);

        // 获取上一年度项目列表
        ProjectQuery lastYearQuery = new ProjectQuery();
        BeanUtils.copyProperties(query, lastYearQuery);
        lastYearQuery.setYear(query.getYear() - 1);
        lastYearQuery.setFirst("1");
        List<Project> lastYearProjects = getProjectsForYear(lastYearQuery);

        // 批量预加载当前年度相关数据
        Map<String, List<ProjectFee>> currentYearFeeMap = batchLoadFees(currentYearProjects);
        Map<String, List<ProjectSale>> currentYearSaleMap = batchLoadSales(currentYearProjects);

        // 批量预加载上一年度相关数据
        Map<String, List<ProjectFee>> lastYearFeeMap = batchLoadFees(lastYearProjects);
        Map<String, List<ProjectSale>> lastYearSaleMap = batchLoadSales(lastYearProjects);

        // 处理当前年度数据
        processProjects(currentYearProjects, currentYearFeeMap, currentYearSaleMap, currentYearTotals);

        // 处理上一年度数据
        processProjects(lastYearProjects, lastYearFeeMap, lastYearSaleMap, lastYearTotals);

        // 构建结果(包含差异值)
        return buildDataViewsWithDiff(currentYearTotals, lastYearTotals, query.getYear());
    }

    @Override
    public DataView getProjectStatus(ProjectQuery query) {
        DataView dataView = new DataView();

        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);
        //设置标题多少个
        Integer currentCount = currentYearProjects != null ? currentYearProjects.size() : 0;
        dataView.setTitle(currentCount);
        // 获取上一年度项目列表
        ProjectQuery lastYearQuery = new ProjectQuery();
        BeanUtils.copyProperties(query, lastYearQuery);
        lastYearQuery.setYear(query.getYear() - 1);
        List<Project> lastYearProjects = getProjectsForYear(lastYearQuery);
        Integer lastCount = lastYearProjects != null ? lastYearProjects.size() : 0;
        Integer diff = currentCount - lastCount;
        dataView.setSubtitle(diff);

        // 统计 createUserName 出现最多的用户
        Map.Entry<String, Long> mostCommonCurrentUser = getMostCommonCreateUser(currentYearProjects);
        String updateString = "";
        if (mostCommonCurrentUser != null) {
            System.out.println("当前年度出现最多的 createUserName: " + mostCommonCurrentUser.getKey() +
                    ", 出现次数: " + mostCommonCurrentUser.getValue());
            updateString = String.valueOf(query.getYear()) + "年新建项目最多的人为: " + mostCommonCurrentUser.getKey() + ",共: " + mostCommonCurrentUser.getValue() + "个";
        } else {
            System.out.println("当前年度没有项目数据。");
            updateString = "暂无数据";
        }
        dataView.setUpdate(updateString);
        BeanUtils.copyProperties(query, lastYearQuery);
        lastYearQuery.setYear(query.getYear() - 1);

// 获取所有项目编号
        List<String> projectNos = currentYearProjects.stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());

        projectNos.add("0");

// 初始化数据对象
        ChartData chartData = new ChartData();
// 确保chartData内部的列表已初始化（如果ChartData类没有默认初始化）
        chartData.setLabels(new ArrayList<>());
        chartData.setData(new ArrayList<>());

// 定义阶段配置
        record PhaseConfig(String phaseId, String label, String status) {
        }
        List<PhaseConfig> configs = List.of(
                new PhaseConfig("2", "项目立项", "1"),
                new PhaseConfig("3", "项目实施", "1"),
                new PhaseConfig("4", "项目验收", "1"),
                new PhaseConfig("5", "项目核算", "1"),
                new PhaseConfig("6", "项目质保", "1"),
                new PhaseConfig("7", "待归档", "1"),
                new PhaseConfig("7", "已归档", "2")
        );

// 统计各阶段项目数量
        configs.forEach(config -> {
            int count = phaseService.count(Wrappers.<ProjectPhase>lambdaQuery()
                    .eq(ProjectPhase::getPhaseId, config.phaseId())
                    .eq(ProjectPhase::getStatus, config.status())
                    .in(ProjectPhase::getProjectNo, projectNos));
            chartData.getLabels().add(config.label());
            chartData.getData().add(count);
        });
        // 设置返回数据
        dataView.setChartData(chartData);
        return dataView;
    }

    @Override
    public CountAndList getWarrantyList(ProjectQuery query) {

        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);
        //设置标题多少个
        Integer currentCount = currentYearProjects != null ? currentYearProjects.size() : 0;

        // 获取所有项目编号
        List<String> projectNos = currentYearProjects.stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());

        projectNos.add("0");

        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        // 初始化数据对象
        ChartData chartData = new ChartData();
        // 1. 查询数据
        LambdaQueryWrapper<ProjectWarranty> warrantyWrapper = new LambdaQueryWrapper<>();
        warrantyWrapper.eq(ProjectWarranty::getStatus, '1'); // 未完成的
        warrantyWrapper.in(ProjectWarranty::getProjectNo, projectNos); // 属于我参与的项目
        warrantyWrapper.ne(ProjectWarranty::getWarranty, BigDecimal.ZERO); // 质保金不等于0的

        List<ProjectWarranty> warrantyList = warrantyService.list(warrantyWrapper);

        // 3. 处理数据（计算截止日期、剩余天数、行状态，并统计逾期金额和数量）
        LocalDate currentDate = LocalDate.now(); // 当前日期

        List<ProjectWarranty> processedWarranties = warrantyList.stream()
                .peek(warranty -> {
                    if (warranty.getStartDate() != null && warranty.getCycle() != null) {
                        // 计算截止日期（起始日期 + 周期月份）
                        LocalDate startDate = warranty.getStartDate().toInstant()
                                .atZone(ZoneId.systemDefault())
                                .toLocalDate();
                        LocalDate endDate = startDate.plusMonths(warranty.getCycle().longValue());

                        // 计算剩余天数
                        long remainingDays = ChronoUnit.DAYS.between(currentDate, endDate);
                        warranty.setWarrantyRemaining((int) remainingDays);

                        // 设置行状态：逾期（1）或未逾期（2）
                        if (remainingDays < 0) {
                            warranty.setRowStatus("1"); // 逾期
                        } else {
                            warranty.setRowStatus("2"); // 未逾期
                        }
                        // 设置截止日期（如果需要）
                        warranty.setEndDate(Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
                    }
                })
                // 按截止日期升序排序（最早的在前）
                .sorted(Comparator.comparing(w ->
                        w.getEndDate() != null ?
                                w.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() :
                                LocalDate.MAX
                ))
//                .limit(10) // 取前20条
                .collect(Collectors.toList());

        for (ProjectWarranty warranty : processedWarranties) {
            //设置项目名称 管家婆项目 发起人
            String projectNo = warranty.getProjectNo();
            Project projectInfo = projectService.getById(projectNo);
            String projectName = projectInfo.getProjectName();
            warranty.setProjectName(projectName);
            String housekeeperName = projectInfo.getHousekeeperName();
            warranty.setHousekeeperName(housekeeperName);
            String createUserName = projectInfo.getCreateUserName();
            warranty.setCreateUser(createUserName);
            BigDecimal settlementAmount = projectInfo.getSettlementAmount();
            warranty.setSettlementAmount(settlementAmount);
            warranty.setPhaseName("项目质保");
            String companyName = projectInfo.getCustomerName();
//            warranty.setCompany(companyName);
        }

        CountAndList countAndList = new CountAndList();
        countAndList.setCount(warrantyList.size());
        countAndList.setTableDataInfo(new TableDataInfo(processedWarranties, page.getTotal()));
        countAndList.setWarrantyList(processedWarranties);
        return countAndList;
    }


    public CountAndList overTimeList(ProjectQuery query) {
        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);

        // 获取所有项目编号
        List<String> projectNos = currentYearProjects.stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());
        projectNos.add("0");

        // 查询 ProjectPhase 数据
        LambdaQueryWrapper<ProjectPhase> phaseWrapper = Wrappers.lambdaQuery();
        phaseWrapper.in(ProjectPhase::getProjectNo, projectNos);
        phaseWrapper.eq(ProjectPhase::getStatus, "1");
        phaseWrapper.and(wrapper -> wrapper.in(ProjectPhase::getPhaseId, Arrays.asList("2", "3", "4")));
        List<ProjectPhase> projectPhaseList = phaseService.list(phaseWrapper);

        // 提取 phase 对应的项目编号 和 phaseId 映射关系
        Map<String, String> projectPhaseMap = projectPhaseList.stream()
                .collect(Collectors.toMap(
                        ProjectPhase::getProjectNo,
                        phase -> phase.getPhaseId(), // 自动覆盖重复的 projectNo，保留最后一个
                        (existing, replacement) -> existing // 如果有多个 phase 记录，保留第一个
                ));

        // 获取交集
        List<String> phaseProjectNo = projectPhaseList.stream()
                .map(ProjectPhase::getProjectNo)
                .collect(Collectors.toList());

        Set<String> set1 = new HashSet<>(projectNos);
        Set<String> set2 = new HashSet<>(phaseProjectNo);

        List<String> intersection = set1.stream()
                .filter(set2::contains)
                .filter(projectNo -> !"0".equals(projectNo))
                .collect(Collectors.toList());

        intersection.add("0");

        // 查询项目列表并排序
        LambdaQueryWrapper<Project> projectWrapper = Wrappers.lambdaQuery();
        projectWrapper.in(Project::getProjectNo, intersection);
        projectWrapper.lt(Project::getAcceptTime, new Date());
        projectWrapper.orderByAsc(Project::getAcceptTime);


        //查询数量
        int count = projectService.count(projectWrapper);

        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> projectList = projectService.list(projectWrapper).stream()
                .collect(Collectors.toList());

        LocalDate now = LocalDate.now();

        for (Project project : projectList) {
            if (project.getAcceptTime() != null) {
                LocalDate acceptDate = project.getAcceptTime().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDate();

                long daysBetween = ChronoUnit.DAYS.between(acceptDate, now);
                project.setOverDays(daysBetween > 0 ? (int) daysBetween : 0);
            } else {
                project.setOverDays(0);
            }

            // 设置 phaseId
            String phaseId = projectPhaseMap.get(project.getProjectNo());
            project.setPhaseId(phaseId != null ? phaseId : "");
        }
        for (Project project : projectList) {
            if ("2".equals(project.getPhaseId())) {
                project.setPhaseName("项目立项");
            } else if ("3".equals(project.getPhaseId())) {
                project.setPhaseName("项目实施");
            } else if ("4".equals(project.getPhaseId())) {
                project.setPhaseName("项目验收");
            }
        }

        CountAndList countAndList = new CountAndList();
        countAndList.setProjectList(projectList);
        countAndList.setCount(count);
        countAndList.setTableDataInfo(new TableDataInfo(projectList, page.getTotal()));
        return countAndList;
    }

    @Override
    public CountAndList getImplement(ProjectQuery query) {
        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);

        // 获取所有项目编号
        List<String> projectNos = currentYearProjects.stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());
        projectNos.add("0");

        // 查询 ProjectPhase 数据
        LambdaQueryWrapper<ProjectPhase> phaseWrapper = Wrappers.lambdaQuery();
        phaseWrapper.in(ProjectPhase::getProjectNo, projectNos);
        phaseWrapper.eq(ProjectPhase::getStatus, "1");
        phaseWrapper.and(wrapper -> wrapper.in(ProjectPhase::getPhaseId, Arrays.asList("3")));
        List<ProjectPhase> projectPhaseList = phaseService.list(phaseWrapper);

        // 获取交集
        List<String> phaseProjectNo = projectPhaseList.stream()
                .map(ProjectPhase::getProjectNo)
                .collect(Collectors.toList());

        Set<String> set1 = new HashSet<>(projectNos);
        Set<String> set2 = new HashSet<>(phaseProjectNo);

        List<String> intersection = set1.stream()
                .filter(set2::contains)
                .filter(projectNo -> !"0".equals(projectNo))
                .collect(Collectors.toList());

        intersection.add("0");

        // 查询项目列表并排序
        LambdaQueryWrapper<Project> projectWrapper = Wrappers.lambdaQuery();
        projectWrapper.in(Project::getProjectNo, intersection);
        projectWrapper.orderByAsc(Project::getCreateTime);

        //查询数量
        int count = projectService.count(projectWrapper);
        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> projectList = projectService.list(projectWrapper).stream()
                .collect(Collectors.toList());
        for (Project project : projectList) {
            project.setPhaseId("3");
            project.setPhaseName("项目实施");
        }

        CountAndList countAndList = new CountAndList();
        countAndList.setCount(count);
        countAndList.setProjectList(projectList);
        countAndList.setTableDataInfo(new TableDataInfo(projectList, page.getTotal()));
        return countAndList;
    }

    @Override
    public TableDataInfo allProjectYear(ProjectQuery query) {
        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);

        // 获取所有项目编号
        List<String> projectNos = currentYearProjects.stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());
        projectNos.add("0");


        query.setProjectList(projectNos);
        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> resultList = projectMapper.getList(query);
        for (Project project : resultList) {
            setOprator(project);
            setCurentPeople(project);
        }
        return new TableDataInfo(resultList, page.getTotal());
    }


    @Override
    public DataView getPieData(ProjectQuery query) {
        DataView dataView = new DataView();

        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);
        //设置标题多少个
        Integer currentCount = currentYearProjects != null ? currentYearProjects.size() : 0;
        dataView.setTitle(currentCount);


        // 获取所有项目编号
        List<String> projectNos = currentYearProjects.stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());

        projectNos.add("0");

        // 初始化数据对象
        ChartData chartData = new ChartData();
        // 1. 查询数据
        LambdaQueryWrapper<ProjectWarranty> warrantyWrapper = new LambdaQueryWrapper<>();
        warrantyWrapper.eq(ProjectWarranty::getStatus, '1'); // 未完成的
        warrantyWrapper.in(ProjectWarranty::getProjectNo, projectNos); // 属于我参与的项目
        List<ProjectWarranty> warrantyList = warrantyService.list(warrantyWrapper);

// 2. 计算质保金总金额
        BigDecimal totalWarrantyMoney = warrantyList.stream()
                .map(ProjectWarranty::getWarranty)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

// 3. 处理数据（计算截止日期、剩余天数、行状态，并统计逾期金额和数量）
        LocalDate currentDate = LocalDate.now(); // 当前日期

// 初始化逾期金额和数量统计
        BigDecimal overdueAmount = BigDecimal.ZERO;
        int overdueCount = 0;

        List<ProjectWarranty> processedWarranties = warrantyList.stream()
                .peek(warranty -> {
                    if (warranty.getStartDate() != null && warranty.getCycle() != null) {
                        // 计算截止日期（起始日期 + 周期月份）
                        LocalDate startDate = warranty.getStartDate().toInstant()
                                .atZone(ZoneId.systemDefault())
                                .toLocalDate();
                        LocalDate endDate = startDate.plusMonths(warranty.getCycle().longValue());

                        // 计算剩余天数
                        long remainingDays = ChronoUnit.DAYS.between(currentDate, endDate);
                        warranty.setWarrantyRemaining((int) remainingDays);

                        // 设置行状态：逾期（1）或未逾期（2）
                        if (remainingDays < 0) {
                            warranty.setRowStatus("1"); // 逾期
                        } else {
                            warranty.setRowStatus("2"); // 未逾期
                        }

                        // 设置截止日期（如果需要）
                        warranty.setEndDate(Date.from(endDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
                    }
                })
                // 按截止日期升序排序（最早的在前）
                .sorted(Comparator.comparing(w ->
                        w.getEndDate() != null ?
                                w.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate() :
                                LocalDate.MAX
                ))
                .collect(Collectors.toList());

        // 4. 计算逾期未收的金额和数量
        for (ProjectWarranty warranty : processedWarranties) {
            if (warranty.getRowStatus() != null && warranty.getRowStatus().equals("1")) {
                // 如果是逾期状态（rowStatus=1），累加金额和数量
                if (warranty.getWarranty() != null) {
                    overdueAmount = overdueAmount.add(warranty.getWarranty());
                }
                overdueCount++;
            }
        }
        String title = "";
        // 使用 StringBuilder 拼接信息
        title = new StringBuilder()
                .append("质保项目总数: ")
                .append(warrantyList != null ? warrantyList.size() : 0)
                .append(" 个，待收总金额: ")
                .append(totalWarrantyMoney != null ? totalWarrantyMoney.stripTrailingZeros().toPlainString() : "0.00")
                .append(" 元")
                .toString();

        dataView.setText(title);
        dataView.setSubtitle(overdueCount);
        dataView.setDiff(overdueAmount);

        // 从已处理的20条数据中，找到第一条未逾期的数据
        Optional<ProjectWarranty> firstNonOverdueWarranty = processedWarranties.stream()
                .filter(w -> "2".equals(w.getRowStatus())) // 筛选未逾期（rowStatus=2）
                .findFirst(); // 取第一条

        // 如果存在，获取该数据；否则返回null（或做其他处理）
        ProjectWarranty targetWarranty = firstNonOverdueWarranty.orElse(null);
        if (targetWarranty != null) {
            String projectNo = targetWarranty.getProjectNo();
            Project project = projectService.getById(projectNo);
            dataView.setUpdate("最近待收质保金项目:" + project.getProjectName() + ",剩余" + targetWarranty.getWarrantyRemaining() + "天到期");
        } else {
            dataView.setUpdate("暂无数据");
        }

        // 设置返回数据
        dataView.setChartData(chartData);
        List<ChartData> chartDataList = calculateWarrantyStats(projectNos);
        dataView.setData(chartDataList);
        return dataView;
    }

    @Override
    public DataView getLineData(ProjectQuery query) {
        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        //统计每个月新建的项目数量
        //统计1月到十二月每个月新建的项目数量有多少
        Integer year = query.getYear();
        LocalDate startDate = LocalDate.of(year, 1, 1);
        LocalDate endDate = LocalDate.of(year + 1, 1, 1);

        // 查询本年度的所有项目
        LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.between(Project::getApprovalDate, startDate, endDate);
        queryWrapper.select(Project::getCreateTime); // 只取创建时间即可
        List<Project> projectList = projectMapper.selectList(queryWrapper);

        //竣工完成进入质保的项目
        List<Integer> warrantyData = new ArrayList<>();

        // 构建查询条件包装器
        LambdaQueryWrapper<ProjectPhase> baseWrapper = Wrappers.lambdaQuery();
        baseWrapper.eq(ProjectPhase::getPhaseId, 6);

        // 使用循环处理每个月（1月到12月）
        for (int month = 1; month <= 12; month++) {
            // 获取当月的第一天
            LocalDate startOfMonth = LocalDate.of(year, month, 1);
            // 获取下个月的第一天（作为结束边界）
            LocalDate endOfMonth = month == 12
                    ? LocalDate.of(year + 1, 1, 1)
                    : LocalDate.of(year, month + 1, 1);

            // 构建时间范围查询：createTime >= startOfMonth 且 createTime < endOfMonth
            LambdaQueryWrapper<ProjectPhase> wrapper = baseWrapper.clone(); // 注意：需要 clone，避免条件叠加
            wrapper.ge(ProjectPhase::getCreateTime, startOfMonth)
                    .lt(ProjectPhase::getCreateTime, endOfMonth);

            // 查询当月符合条件的数据数量
            Integer count = projectPhaseMapper.selectCount(wrapper);
            warrantyData.add(count);
        }


        //归档的项目
        List<Integer> completeData = new ArrayList<>();


        // 构建查询条件包装器
        LambdaQueryWrapper<ProjectPhase> comWrapper = Wrappers.lambdaQuery();
        comWrapper.eq(ProjectPhase::getPhaseId, 7);

        // 使用循环处理每个月（1月到12月）
        for (int month = 1; month <= 12; month++) {
            // 获取当月的第一天
            LocalDate startOfMonth = LocalDate.of(year, month, 1);
            // 获取下个月的第一天（作为结束边界）
            LocalDate endOfMonth = month == 12
                    ? LocalDate.of(year + 1, 1, 1)
                    : LocalDate.of(year, month + 1, 1);

            // 构建时间范围查询：createTime >= startOfMonth 且 createTime < endOfMonth
            LambdaQueryWrapper<ProjectPhase> wrapper = comWrapper.clone(); // 注意：需要 clone，避免条件叠加
            wrapper.ge(ProjectPhase::getCreateTime, startOfMonth)
                    .lt(ProjectPhase::getCreateTime, endOfMonth);

            // 查询当月符合条件的数据数量
            Integer count = projectPhaseMapper.selectCount(wrapper);
            completeData.add(count);
        }


        // 存储结果：key=月份（1~12），value=项目数量
        Map<Integer, Long> monthlyCountMap = projectList.stream()
                .filter(project -> project.getCreateTime() != null)
                .collect(Collectors.groupingBy(
                        project -> {
                            LocalDate date = project.getCreateTime().toInstant()
                                    .atZone(ZoneId.systemDefault())
                                    .toLocalDate();
                            return date.getMonthValue(); // 获取月份（1-12）
                        },
                        Collectors.counting()
                ));

        String[] labels = {"一月", "二月", "三月", "四月", "五月", "六月",
                "七月", "八月", "九月", "十月", "十一月", "十二月"};
        List<Integer> data = new ArrayList<>();
        LocalDate now = LocalDate.now(); // 当前日期
        int currentMonth = now.getMonthValue(); // 当前月份（1~12）
        int currentYear = now.getYear(); // 当前年份
        // 判断是否是当年
        if (year == currentYear) {
            for (int i = 1; i <= currentMonth; i++) {
                data.add(Math.toIntExact(monthlyCountMap.getOrDefault(i, 0L)));
            }
        } else {
            for (int i = 1; i <= 12; i++) {
                data.add(Math.toIntExact(monthlyCountMap.getOrDefault(i, 0L)));
            }
        }


        DataView dataView = new DataView();
        List<ChartData> chartDataList = new ArrayList<>();
        ChartData chartDataWa = new ChartData();
        chartDataWa.setData(warrantyData);
        chartDataWa.setBorderColor("#ff6384");
        chartDataWa.setBackgroundColor("transparent");
        chartDataWa.setLabel("新增质保数");


        ChartData chartDataCom = new ChartData();
        chartDataCom.setData(completeData);
        chartDataCom.setBorderColor("#36a2eb");
        chartDataCom.setBackgroundColor("transparent");
        chartDataCom.setLabel("新增归档数");


        ChartData chartData = new ChartData();
        chartData.setData(data);
        chartDataList.add(chartData);
        chartData.setBorderColor("#cc65fe");
        chartData.setBackgroundColor("transparent");
        chartData.setLabel("新增项目数");

        chartDataList.add(chartDataWa);

        chartDataList.add(chartDataCom);

        dataView.setLabels(Arrays.stream(labels).toList());
        dataView.setDatasets(chartDataList);

        Optional<Map.Entry<Integer, Long>> maxEntry = monthlyCountMap.entrySet()
                .stream()
                .max(Map.Entry.comparingByValue());

        if (maxEntry.isPresent()) {
            int month = maxEntry.get().getKey();
            long count = maxEntry.get().getValue();
            String monthName = labels[month - 1];
            System.out.println();
            String title = "新增项目最多的月份是：" + monthName + "，共新增 " + count + " 个项目。";
            dataView.setText(title);
        } else {
            System.out.println("没有项目数据。");
            dataView.setText("暂无数据");
        }

        if (CollectionUtils.isNotEmpty(projectList)) {
            String update = "";
            update = "合计共" + projectList.size() + "个项目";
            dataView.setUpdate(update);
        } else {
            dataView.setUpdate("暂无数据");
        }

        return dataView;
    }

    @Override
    public Map<String, List<DataView>> getRank(ProjectQuery query) {

        Map<String, List<DataView>> map = new HashMap<>();

        Integer year = query.getYear();
        LocalDate startDate = LocalDate.of(year, 1, 1);
        LocalDate endDate = LocalDate.of(year + 1, 1, 1);
        Long userId = SecurityUtils.getLoginUser().getUserId();
        if (query.getRefresh().equals("1")) {
            try {
                map = (Map<String, List<DataView>>) redisCache.redisTemplate.opsForValue().get("rank" + String.valueOf(query.getYear()));
            } catch (RuntimeException e) {
                map = null;
            }
            if (map != null) {
                return map;
            }
            map = new HashMap<>();
        }

// 查询本年度的所有项目编号
        LambdaQueryWrapper<Project> queryWrapperProject = Wrappers.lambdaQuery();
        queryWrapperProject.between(Project::getApprovalDate, startDate, endDate)
                .select(Project::getProjectNo);

// 获取 List<String> 类型的 projectNo 列表
        List<String> projectNoList = projectService.list(queryWrapperProject).stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());

        projectNoList.add("0");
        //参与人员 挑选出销售负责人 项目经理 按照用户id分组统计
        LambdaQueryWrapper<ProjectParticipan> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(ProjectParticipan::getPostId, Arrays.asList(5L, 2L))
                .select(ProjectParticipan::getParticipantId,
                        ProjectParticipan::getParticipanName,
                        ProjectParticipan::getProjectNo)
                .in(ProjectParticipan::getProjectNo, projectNoList);

        List<ProjectParticipan> joinList = participanService.list(queryWrapper);

        Map<Long, ProjectParticipan> dtoMap = joinList.stream()
                .filter(item -> item.getParticipantId() != null && item.getProjectNo() != null)
                .collect(Collectors.groupingBy(
                        ProjectParticipan::getParticipantId,
                        Collectors.collectingAndThen(Collectors.toList(), group -> {
                            ProjectParticipan dto = new ProjectParticipan();
                            dto.setParticipantId(group.get(0).getParticipantId());
                            dto.setParticipanName(group.get(0).getParticipanName());
                            dto.setProjectNos(group.stream()
                                    .map(ProjectParticipan::getProjectNo)
                                    .distinct()
                                    .collect(Collectors.toList()));
                            return dto;
                        })
                ));

        List<ProjectParticipan> resultJoin = new ArrayList<>(dtoMap.values());

        // 销售排行榜
        List<DataView> dataViewList = new ArrayList<>();

// 利润排行榜
        List<DataView> profitViewList = new ArrayList<>();

// 利润率排行榜
        List<DataView> profitRateViewList = new ArrayList<>();

// 统计数据：销售额、利润
        Map<String, BigDecimal> saleMap = new HashMap<>();
        Map<String, BigDecimal> profitMap = new HashMap<>();

        for (ProjectParticipan dto : resultJoin) {
            List<String> projectNos = dto.getProjectNos();
            BigDecimal saleTotal = BigDecimal.ZERO;
            BigDecimal costTotal = BigDecimal.ZERO;

            //过滤出已经有正式清单或正式合同的项目


// 查询已经有正式清单或正式合同的项目编号
            List<String> filteredProjectNos = phaseService.selectDistinctProjectNoByPhaseId("3");

// 取交集：保留 projectNos 中也存在于 filteredProjectNos 中的项
            projectNos.retainAll(filteredProjectNos);

            for (String projectNo : projectNos) {
                Project projectInfo = projectService.getById(projectNo);
                String housekeeperProject = projectInfo.getHousekeeperProject();
                if (StringUtils.isNotEmpty(housekeeperProject)) {
                    LambdaQueryWrapper<ProjectSale> saleWrapper = Wrappers.lambdaQuery();
                    saleWrapper.eq(ProjectSale::getHousekeeperProject, housekeeperProject);
                    List<ProjectSale> saleList = saleService.list(saleWrapper);

                    for (ProjectSale sale : saleList) {
                        if ("00021".equals(sale.getGoodsId())) continue; // 过滤开票

                        saleTotal = saleTotal.add(Optional.ofNullable(sale.getTotal()).map(BigDecimal::negate).orElse(BigDecimal.ZERO));
                        costTotal = costTotal.add(Optional.ofNullable(sale.getCostTotal()).map(BigDecimal::negate).orElse(BigDecimal.ZERO));
                    }
                }
            }

            BigDecimal profitTotal = saleTotal.subtract(costTotal);
            saleMap.put(dto.getParticipanName(), saleTotal);
            profitMap.put(dto.getParticipanName(), profitTotal);
        }

// 按销售额从大到小排序
        List<Map.Entry<String, BigDecimal>> sortedSales = saleMap.entrySet()
                .stream()
                .sorted(Map.Entry.<String, BigDecimal>comparingByValue().reversed())
                .collect(Collectors.toList());

// 按利润从大到小排序
        List<Map.Entry<String, BigDecimal>> sortedProfit = profitMap.entrySet()
                .stream()
                .sorted(Map.Entry.<String, BigDecimal>comparingByValue().reversed())
                .collect(Collectors.toList());

// 按利润率从大到小排序
        Map<String, BigDecimal> profitRateMap = new HashMap<>();
        saleMap.forEach((name, sales) -> {
            BigDecimal profit = profitMap.getOrDefault(name, BigDecimal.ZERO);
            BigDecimal profitRate = BigDecimal.ZERO;
            if (sales.compareTo(BigDecimal.ZERO) > 0) {
                profitRate = profit.divide(sales, 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
            }
            profitRateMap.put(name, profitRate);
        });

        List<Map.Entry<String, BigDecimal>> sortedProfitRate = profitRateMap.entrySet()
                .stream()
                .sorted(Map.Entry.<String, BigDecimal>comparingByValue().reversed())
                .collect(Collectors.toList());

// 生成排行榜
        generateRanking(sortedSales, saleMap, profitMap, dataViewList, "销售");
        generateRanking(sortedProfit, saleMap, profitMap, profitViewList, "利润");
        generateRanking(sortedProfitRate, saleMap, profitMap, profitRateViewList, "利润率");
        map.put("dataViewList", dataViewList);
        map.put("profitViewList", profitViewList);
        map.put("profitRateViewList", profitRateViewList);
        redisCache.redisTemplate.opsForValue().set("rank" + String.valueOf(year), map, 2, TimeUnit.HOURS);
        return map;
    }


    private void generateRanking(List<Map.Entry<String, BigDecimal>> sortedList,
                                 Map<String, BigDecimal> saleMap,
                                 Map<String, BigDecimal> profitMap,
                                 List<DataView> targetList,
                                 String rankType) {

        int loopCount = sortedList.size() > 5 ? 5 : sortedList.size();
        for (int i = 0; i < loopCount; i++) {
            Map.Entry<String, BigDecimal> entry = sortedList.get(i);
            String name = entry.getKey();

            BigDecimal sales = saleMap.getOrDefault(name, BigDecimal.ZERO);
            BigDecimal profit = profitMap.getOrDefault(name, BigDecimal.ZERO);

            BigDecimal value = entry.getValue(); // 当前排行榜依据值（可能是销售额、利润或利润率）

            // 排名标题
            String rankTitle;
            if (i == 0) {
                rankTitle = "冠军";
            } else if (i == 1) {
                rankTitle = "亚军";
            } else if (i == 2) {
                rankTitle = "季军";
            } else {
                rankTitle = "第" + (i + 1) + "名";
            }

            // 构造显示文本
            String text;
            if ("利润率".equals(rankType)) {
                BigDecimal profitAmount = profitMap.getOrDefault(name, BigDecimal.ZERO);
                BigDecimal profitInWan = profitAmount.divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                // 构建子文本，并确保利润额单独一行显示
                String subText = String.format("利润额：¥%.2f 万元", profitInWan);
                // 使用 \n 换行，把利润信息放到下一行
                text = String.format("%s：%s :  %.2f%%\n%s", rankTitle, name, value, subText);
            } else {
                BigDecimal amountInWan = value.divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                String subText = String.format("利润：¥%.2f 万元", profit.divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP));
                if ("销售".equals(rankType)) {
                    text = String.format("%s：%s : ¥%.2f 万元", rankTitle, name, amountInWan);
                } else { // 利润
                    text = String.format("%s：%s : ¥%.2f 万元", rankTitle, name, amountInWan);
                }
            }

            DataView dataView = new DataView();
            dataView.setText(text);
            targetList.add(dataView);
        }
    }


    @Override
    public CountAndList waitPayment(ProjectQuery query) {
        DataView dataView = new DataView();

        // 设置用户ID
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);

        // 获取当前年度项目列表
        List<Project> currentYearProjects = getProjectsForYear(query);

        // 获取所有项目编号
        List<String> projectNos = currentYearProjects.stream()
                .map(Project::getProjectNo)
                .collect(Collectors.toList());
        projectNos.add("0");

        LambdaQueryWrapper<ProjectPhase> phaseWrapper = Wrappers.lambdaQuery();
        phaseWrapper.in(ProjectPhase::getProjectNo, projectNos);
        phaseWrapper.eq(ProjectPhase::getStatus, "1");
        //验收核算进行中的
        phaseWrapper.and(wrapper -> wrapper.in(ProjectPhase::getPhaseId, Arrays.asList("4", "5")));
        List<ProjectPhase> projectPhaseList = phaseService.list(phaseWrapper);
        // 获取所有项目编号
        List<String> phaseProjectNo = projectPhaseList.stream()
                .map(ProjectPhase::getProjectNo)
                .collect(Collectors.toList());

        Set<String> set1 = new HashSet<>(projectNos);
        Set<String> set2 = new HashSet<>(phaseProjectNo);

        List<String> intersection = set1.stream()
                .filter(set2::contains)
                .filter(projectNo -> !"0".equals(projectNo)) // 排除 "0"
                .collect(Collectors.toList());

        intersection.add("0");

        query.setProjectList(intersection);
        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> projectList = projectMapper.getList(query);

        CountAndList countAndList = new CountAndList();
        countAndList.setCount(projectList.size());
        countAndList.setProjectList(projectList);
        countAndList.setTableDataInfo(new TableDataInfo(projectList, page.getTotal()));
        return countAndList;
    }

    public List<ChartData> calculateWarrantyStats(List<String> projectNos) {
        // 1. 查询未完成的质保数据
        LambdaQueryWrapper<ProjectWarranty> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProjectWarranty::getStatus, '1');
        wrapper.in(ProjectWarranty::getProjectNo, projectNos);
        List<ProjectWarranty> warranties = warrantyService.list(wrapper);

        // 2. 初始化统计结果对象
        WarrantyStatsVO stats = new WarrantyStatsVO();
        LocalDate today = LocalDate.now();

        // 3. 遍历数据并分类统计
        for (ProjectWarranty warranty : warranties) {
            if (warranty.getStartDate() == null || warranty.getCycle() == null) {
                continue;
            }

            // 计算截止日期
            LocalDate startDate = warranty.getStartDate().toInstant()
                    .atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate endDate = startDate.plusMonths(warranty.getCycle().longValue());
            long daysRemaining = ChronoUnit.DAYS.between(today, endDate);
            List<ChartData> list = new ArrayList<>();
            // 统计逾期数据
            if (daysRemaining < 0) {
                stats.setOverdueCount(stats.getOverdueCount() + 1);
                if (warranty.getWarranty() != null) {
                    stats.setOverdueAmount(stats.getOverdueAmount().add(warranty.getWarranty()));
                }
                continue;
            }

            // 计算剩余月份数（向上取整）
            long monthsRemaining = ChronoUnit.MONTHS.between(today, endDate);
            if (today.getDayOfMonth() < endDate.getDayOfMonth()) {
                monthsRemaining += 1;
            }


            // 按月份区间统计待收金额（非交叉）
            BigDecimal amount = warranty.getWarranty() != null ? warranty.getWarranty() : BigDecimal.ZERO;
            if (monthsRemaining <= 1) {
                stats.setPending1Month(stats.getPending1Month().add(amount));
            } else if (monthsRemaining <= 2) {
                stats.setPending2Month(stats.getPending2Month().add(amount));
            } else if (monthsRemaining <= 3) {
                stats.setPending3Month(stats.getPending3Month().add(amount));
            } else if (monthsRemaining <= 4) {
                stats.setPending4Month(stats.getPending4Month().add(amount));
            } else if (monthsRemaining <= 5) {
                stats.setPending5Month(stats.getPending5Month().add(amount));
            }
        }

        List<ChartData> list = new ArrayList<>();
        ChartData over = new ChartData();
        if (stats.getOverdueAmount().compareTo(BigDecimal.ZERO) > 0) {
            over.setName("已逾期");
            over.setValue(String.valueOf(stats.getOverdueAmount()));
            list.add(over);
        }
        // 添加各月份待收数据
        addMonthData(list, stats.getPending1Month(), "近一个月");
        addMonthData(list, stats.getPending2Month(), "近两个月");
        addMonthData(list, stats.getPending3Month(), "近三个月");
        addMonthData(list, stats.getPending4Month(), "近四个月");
        addMonthData(list, stats.getPending5Month(), "近五个月");

        if (CollectionUtils.isEmpty(list)) {
            ChartData result = new ChartData();
            result.setName("近五个月暂无待收质保金项目");
            result.setValue("0");
            list.add(result);
        }

        return list;
    }

    private void addMonthData(List<ChartData> list, BigDecimal amount, String name) {
        if (amount.compareTo(BigDecimal.ZERO) > 0) {
            ChartData data = new ChartData();
            data.setName(name);
            data.setValue(amount.toString());
            list.add(data);
        }
    }


    /**
     * 统计项目列表中出现最多的 createUserName
     *
     * @param projects 项目列表
     * @return 包含用户名和出现次数的 Map.Entry，如果没有数据则返回 null
     */
    public static Map.Entry<String, Long> getMostCommonCreateUser(List<Project> projects) {
        if (projects == null || projects.isEmpty()) {
            return null;
        }

        Map<String, Long> userCountMap = projects.stream()
                .filter(project -> project.getCreateUserName() != null && !project.getCreateUserName().isEmpty())
                .collect(Collectors.groupingBy(Project::getCreateUserName, Collectors.counting()));

        return Collections.max(userCountMap.entrySet(), Map.Entry.comparingByValue());
    }


    // 辅助方法：构建包含差异值的数据视图
    private List<DataView> buildDataViewsWithDiff(BigDecimal[] currentYearTotals, BigDecimal[] lastYearTotals, Integer year) {
        List<DataView> dataViewList = new ArrayList<>();


        // 配合项目总金额
        DataView contractAmountViewAssist = createDataViewWithDiff(
                "配合项目总金额(万元)",
                currentYearTotals[4].divide(TEN_THOUSAND, 2, RoundingMode.DOWN),
                lastYearTotals[4].divide(TEN_THOUSAND, 2, RoundingMode.DOWN)
        );

        // 项目总金额
        DataView contractAmountView = createDataViewWithDiff(
                "项目总金额(万元)",
                currentYearTotals[0].divide(TEN_THOUSAND, 2, RoundingMode.DOWN),
                lastYearTotals[0].divide(TEN_THOUSAND, 2, RoundingMode.DOWN)
        );

        // 结算总金额
        DataView settlementAmountView = createDataViewWithDiff(
                "结算总金额(万元)",
                currentYearTotals[1].divide(TEN_THOUSAND, 2, RoundingMode.DOWN),
                lastYearTotals[1].divide(TEN_THOUSAND, 2, RoundingMode.DOWN)
        );

        // 收款总金额
        DataView receivedAmountView = createDataViewWithDiff(
                "收款总金额(万元)",
                currentYearTotals[2].divide(TEN_THOUSAND, 2, RoundingMode.DOWN),
                lastYearTotals[2].divide(TEN_THOUSAND, 2, RoundingMode.DOWN)
        );

        // 开票总金额
        DataView invoiceAmountView = createDataViewWithDiff(
                "开票总金额(万元)",
                currentYearTotals[3].divide(TEN_THOUSAND, 2, RoundingMode.DOWN),
                lastYearTotals[3].divide(TEN_THOUSAND, 2, RoundingMode.DOWN)
        );

        dataViewList.add(contractAmountView);
        dataViewList.add(contractAmountViewAssist);
        dataViewList.add(settlementAmountView);
        dataViewList.add(receivedAmountView);
        dataViewList.add(invoiceAmountView);

        Long userId = SecurityUtils.getUserId();

        redisCache.redisTemplate.opsForValue().set(String.valueOf(userId) + "firstPanel" + String.valueOf(year), dataViewList, 12, TimeUnit.HOURS);
        return dataViewList;
    }

    // 辅助方法：创建包含差异值的数据视图
    private DataView createDataViewWithDiff(String text, BigDecimal currentValue, BigDecimal lastValue) {
        DataView view = new DataView();
        view.setText(text);
        view.setValue(currentValue);

        // 计算差异值
        BigDecimal diff = currentValue.subtract(lastValue);
        view.setDiff(diff);

        return view;
    }

// 其他辅助方法保持不变(getProjectsForYear, batchLoadFees, batchLoadSales, processProjects等)

    // 辅助方法：获取项目列表
    private List<Project> getProjectsForYear(ProjectQuery query) {
        Integer year = query.getYear();
        LocalDate startDate = LocalDate.of(year, 1, 1);
        LocalDate endDate = LocalDate.of(year + 1, 1, 1);

        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {

            // 查询本年度的所有项目
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();

            //如果是查询所有年年度的
            if (query.getAllYear() == 0) {
                queryWrapper.between(Project::getApprovalDate, startDate, endDate);
            }
            List<String> projectNos = new ArrayList<>();
            //如果查询的是数据看板的第一个板块的内容 管理员  看所有 项目总金额 有结算金额取结算金额 没有结算金额取合同金额 前提是这个项目已经进入了实施
            if (StringUtils.isNotEmpty(query.getFirst()) && "1".equals(query.getFirst())) {
                List<String> strings = phaseService.selectDistinctProjectNoByPhaseId("3");//方法改变过  查询有正式清单或正式合同

                List<Project> list = projectMapper.selectList(queryWrapper);

                // 设置项目编号列表
                List<String> allProjectNo = list.stream()
                        .map(Project::getProjectNo)
                        .collect(Collectors.toCollection(() -> new ArrayList<>(list.size() + 1)));

                Set<String> validProjectNos = new HashSet<>(strings);

                List<String> intersection = allProjectNo.stream()
                        .filter(validProjectNos::contains)
                        .collect(Collectors.toList());
                intersection.add("0");
                if (CollectionUtils.isNotEmpty(strings)) {
                    projectNos.addAll(intersection);
                }
            } else {
                List<Project> list = projectMapper.selectList(queryWrapper);

                // 设置项目编号列表
                List<String> allProjectNo = list.stream()
                        .map(Project::getProjectNo)
                        .collect(Collectors.toCollection(() -> new ArrayList<>(list.size() + 1)));

                projectNos.addAll(allProjectNo);
            }
            projectNos.add("0");
            query.setProjectList(projectNos);

            return projectMapper.getList(query);
        } else {
            // 获取用户发起和参与的项目
            Set<String> projectNos = new LinkedHashSet<>();

            //如果查询的是第一个板块的统计内容 特殊处理 其他用户  判断是不是项目经理 销售负责人
            if (StringUtils.isNotEmpty(query.getFirst()) && "1".equals(query.getFirst())) {

                // 第一部分：获取已经有正式清单或正式合同的项目
                List<String> strings = phaseService.selectDistinctProjectNoByPhaseId("3");
                strings.add("0");
                // 第二部分：获取当前用户是销售负责人或项目经理的项目的 projectNo
                Long userId = SecurityUtils.getUserId();
                LambdaQueryWrapper<ProjectParticipan> saleOrMangerWrapper = Wrappers.lambdaQuery();
                saleOrMangerWrapper.eq(ProjectParticipan::getParticipantId, userId);
                saleOrMangerWrapper.in(ProjectParticipan::getPostId, Arrays.asList("2", "5"));
                // 只查询 projectNo 字段
                List<ProjectParticipan> list = participanService.list(saleOrMangerWrapper);
                List<String> projectNoList = list.stream()
                        .map(ProjectParticipan::getProjectNo)
                        .collect(Collectors.toList());
                projectNoList.add("0");
                // 取两个 List 的交集
                List<String> intersection = new ArrayList<>(new HashSet<>(strings));
                intersection.retainAll(new HashSet<>(projectNoList));
                intersection.add("0");
                //当前年份的
                LambdaQueryWrapper<Project> projectWrapper = Wrappers.lambdaQuery();
                projectWrapper.in(Project::getProjectNo, intersection);
                projectWrapper.between(Project::getApprovalDate, startDate, endDate);
                projectWrapper.select(Project::getProjectNo);

                List<Object> nameObjects = this.baseMapper.selectObjs(projectWrapper);
                nameObjects.stream()
                        .map(obj -> (String) obj)
                        .forEach(projectNos::add);

            } else {
                // 用户发起的项目
                LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
                queryWrapper.between(Project::getApprovalDate, startDate, endDate);
                queryWrapper.select(Project::getProjectNo);

                List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
                nameObjects.stream()
                        .map(obj -> (String) obj)
                        .forEach(projectNos::add);

                // 用户参与的项目
                List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
                currentUserJoinProject.add("0");

                // 构造查询条件
                LambdaQueryWrapper<Project> queryWrapperCurrentYear = Wrappers.lambdaQuery();
                // 查询 立项日期approvalDate 在 [startDate, endDate) 之间的项目
//            queryWrapperCurrentYear.between(Project::getApprovalDate, startDate, endDate);

                //如果是查询所有年年度的
                if (query.getAllYear() == 0) {
                    queryWrapperCurrentYear.between(Project::getApprovalDate, startDate, endDate);
                }

                queryWrapperCurrentYear.in(Project::getProjectNo, currentUserJoinProject);
                queryWrapperCurrentYear.select(Project::getProjectNo);
                // 执行查询
                List<Object> currentList = this.baseMapper.selectObjs(queryWrapperCurrentYear);
                List<String> resultProject = new ArrayList<>(currentList.stream()
                        .map(obj -> (String) obj)
                        .toList());
                projectNos.addAll(resultProject);
            }
            if (projectNos.isEmpty()) {
                projectNos.add("0");
            }

            query.setProjectList(new ArrayList<>(projectNos));
            return projectMapper.getList(query);
        }
    }

    // 辅助方法：批量加载费用数据
    private Map<String, List<ProjectFee>> batchLoadFees(List<Project> projects) {
        Set<String> housekeeperProjects = projects.stream()
                .map(Project::getHousekeeperProject)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toSet());

        if (housekeeperProjects.isEmpty()) {
            return Collections.emptyMap();
        }

        LambdaQueryWrapper<ProjectFee> wrapper = new LambdaQueryWrapper<ProjectFee>()
                .in(ProjectFee::getHousekeeperProject, housekeeperProjects)
                .eq(ProjectFee::getUseType, "1")
                .in(ProjectFee::getMainType, Arrays.asList("4"));

        return feeService.list(wrapper)
                .stream()
                .collect(Collectors.groupingBy(ProjectFee::getHousekeeperProject));
    }

    // 辅助方法：批量加载销售数据
    private Map<String, List<ProjectSale>> batchLoadSales(List<Project> projects) {
        Set<String> housekeeperProjects = projects.stream()
                .map(Project::getHousekeeperProject)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toSet());

        if (housekeeperProjects.isEmpty()) {
            return Collections.emptyMap();
        }

        LambdaQueryWrapper<ProjectSale> wrapper = new LambdaQueryWrapper<ProjectSale>()
                .in(ProjectSale::getHousekeeperProject, housekeeperProjects)
                .eq(ProjectSale::getGoodsId, "00021")
                .orderByAsc(ProjectSale::getSaleDate);

        return saleService.list(wrapper)
                .stream()
                .collect(Collectors.groupingBy(ProjectSale::getHousekeeperProject));
    }

    // 辅助方法：处理项目数据
    private void processProjects(List<Project> projects,
                                 Map<String, List<ProjectFee>> feeMap,
                                 Map<String, List<ProjectSale>> saleMap,
                                 BigDecimal[] totals) {
        for (Project project : projects) {
            setOprator(project);
            setCurentPeople(project);

            // 累加合同金额 有结算金额取结算金额 配合项目的
            if (project.getContractAmount() != null && "4".equals(project.getProjectType())) {
                totals[4] = totals[4].add(project.getSettlementAmount() != null ? project.getSettlementAmount() : project.getContractAmount());
            }

            // 累加合同金额 有结算金额取结算金额
            if (project.getContractAmount() != null) {
                totals[0] = totals[0].add(project.getSettlementAmount() != null ? project.getSettlementAmount() : project.getContractAmount());
            }

            // 累加结算金额
            if (project.getSettlementAmount() != null) {
                totals[1] = totals[1].add(project.getSettlementAmount());
            }

            // 处理实收金额
            if (StringUtils.isNotEmpty(project.getHousekeeperProject())) {
                List<ProjectFee> fees = feeMap.getOrDefault(project.getHousekeeperProject(), Collections.emptyList());
                for (ProjectFee fee : fees) {
                    if (fee.getTotal() != null) {
                        totals[2] = totals[2].add(fee.getTotal());
                    }
                }
            }

            // 处理开票金额
            if (StringUtils.isNotEmpty(project.getHousekeeperProject())) {
                List<ProjectSale> sales = saleMap.getOrDefault(project.getHousekeeperProject(), Collections.emptyList());
                for (ProjectSale sale : sales) {
                    if (sale.getInvoiceAmount() != null) {
                        totals[3] = totals[3].add(sale.getInvoiceAmount());
                    }
                }
            }
        }
    }

    // 辅助方法：构建空的数据视图
    private List<DataView> buildEmptyDataViews() {
        List<DataView> dataViewList = new ArrayList<>();
        BigDecimal zero = BigDecimal.ZERO.setScale(2, RoundingMode.DOWN);

        dataViewList.add(createDataView("项目总金额(万元)", zero));
        dataViewList.add(createDataView("结算总金额(万元)", zero));
        dataViewList.add(createDataView("收款总金额(万元)", zero));
        dataViewList.add(createDataView("开票总金额(万元)", zero));

        return dataViewList;
    }

    // 辅助方法：构建数据视图
    private List<DataView> buildDataViews(BigDecimal contractAmount, BigDecimal settlementAmount,
                                          BigDecimal receivedAmount, BigDecimal invoiceAmount) {
        List<DataView> dataViewList = new ArrayList<>();

        dataViewList.add(createDataView("项目总金额(万元)",
                contractAmount.divide(TEN_THOUSAND, 2, RoundingMode.DOWN)));
        dataViewList.add(createDataView("结算总金额(万元)",
                settlementAmount.divide(TEN_THOUSAND, 2, RoundingMode.DOWN)));
        dataViewList.add(createDataView("收款总金额(万元)",
                receivedAmount.divide(TEN_THOUSAND, 2, RoundingMode.DOWN)));
        dataViewList.add(createDataView("开票总金额(万元)",
                invoiceAmount.divide(TEN_THOUSAND, 2, RoundingMode.DOWN)));

        return dataViewList;
    }

    // 辅助方法：创建单个数据视图
    private DataView createDataView(String text, BigDecimal value) {
        DataView view = new DataView();
        view.setText(text);
        view.setValue(value);
        return view;
    }


    @Override
    public List<Project> myAccountingList(ProjectQuery query) {
        //核算中的 还要过滤一下 是不是我参与的
        Long userId = SecurityUtils.getUserId();
        List<Project> accountingList = projectMapper.getAccountingList();
        List<String> projectNoList = new ArrayList<>();
        projectNoList.add("0");
        for (Project project : accountingList) {
            String projectNo = project.getProjectNo();
            projectNoList.add(projectNo);
        }
        if (userId.equals(100L)) {
            return accountingList;
        }
        LambdaQueryWrapper<ProjectParticipan> joinWrapper = Wrappers.lambdaQuery();
        joinWrapper.eq(ProjectParticipan::getParticipantId, userId);
        joinWrapper.in(ProjectParticipan::getProjectNo, projectNoList);
        List<ProjectParticipan> joinList = participanService.list(joinWrapper);
        List<String> result = new ArrayList<>();
        result.add("0");
        for (ProjectParticipan p : joinList) {
            result.add(p.getProjectNo());
        }

        LambdaQueryWrapper<Project> resultWrapper = Wrappers.lambdaQuery();
        resultWrapper.in(Project::getProjectNo, result);
        return this.list(resultWrapper);
    }

    @Override
    public TableDataInfo getMyCreateListPage(ProjectQuery query) {

        LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
        List<Project> list = projectMapper.selectList(queryWrapper);
        List<String> projectNoList = new ArrayList<>(list.size());
        projectNoList.add("0");
        for (Project project : list) {
            projectNoList.add(project.getProjectNo());
        }
        query.setProjectList(projectNoList);
        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        List<Project> resultList = projectMapper.getList(query);
        for (Project project : resultList) {
            setOprator(project);
            setCurentPeople(project);
        }
        return new TableDataInfo(resultList, page.getTotal());
    }

    @Override
    public TableDataInfo needHandleProject(ProjectQuery query) {
        //需我处理的项目 在环节中需要我去点击下一步的项目
        //1.先获取我参与的并且是进行中的全部项目、

        Long userId = SecurityUtils.getUserId();
        Set<String> adminSet = new HashSet<>();
        //如果是吴总 查询核算环节进行中的 5.22改 吴总也可能是销售负责人
        if (String.valueOf(userId).equals("100")) {
//            List<String> accounting = new ArrayList<>();
            LambdaQueryWrapper<ProjectPhase> phaseQueryWrapper = Wrappers.lambdaQuery();
            phaseQueryWrapper.eq(ProjectPhase::getPhaseId, "5");
            phaseQueryWrapper.eq(ProjectPhase::getStatus, "1");
            phaseQueryWrapper.ne(ProjectPhase::getPhaseId, "6");
            List<ProjectPhase> phaseList = phaseService.list(phaseQueryWrapper);
            for (ProjectPhase phase : phaseList) {
                adminSet.add(phase.getProjectNo());
            }
        }

        //环节进行中的项目
        LambdaQueryWrapper<ProjectPhase> phaseQueryWrapper = Wrappers.lambdaQuery();
        phaseQueryWrapper.eq(ProjectPhase::getStatus, "1");
        phaseQueryWrapper.ne(ProjectPhase::getPhaseId, "6");//剔除质保的
        phaseQueryWrapper.eq(StringUtils.isNotEmpty(query.getPhaseId()), ProjectPhase::getPhaseId, query.getPhaseId());
        List<ProjectPhase> phaseList = phaseService.list(phaseQueryWrapper);
        List<String> projectNoList = new ArrayList<>();
        projectNoList.add("0");
        for (ProjectPhase phase : phaseList) {
//            if ("HCICT2025050023".equals(phase.getProjectNo())) {
            projectNoList.add(phase.getProjectNo());
//            }
        }

        //进行中且是我参与的项目
        LambdaQueryWrapper<ProjectParticipan> joinWrapper = Wrappers.lambdaQuery();
        joinWrapper.eq(ProjectParticipan::getParticipantId, userId);
        joinWrapper.in(ProjectParticipan::getProjectNo, projectNoList);
        List<ProjectParticipan> joinList = participanService.list(joinWrapper);
        System.out.println("join" + joinList);


        List<ProjectPhase> resultPhaseList = new ArrayList<>();
        for (ProjectParticipan join : joinList) {
            for (ProjectPhase p : phaseList) {
                if (join.getProjectNo().equals(p.getProjectNo())) {
                    resultPhaseList.add(p);
                }
            }
        }

        //获得过滤掉的

        Set<String> resultProjectNoList = new HashSet<>();

        for (ProjectPhase p : resultPhaseList) {

            String phaseId = p.getPhaseId();
            if (phaseId == null || !phaseId.matches("\\d+")) {
                continue; // 跳过无效的 phaseId
            }

            List<Integer> audit = p.getAudit();
            if (audit == null) {
                audit = new ArrayList<>();
            }

            PhaseDictionary config = phaseDictionaryService.getById(Long.valueOf(phaseId));
            if (config == null) {
                continue; // 跳过无效的配置
            }

            List<Integer> postId = config.getPostId();
            if (postId == null) {
                postId = new ArrayList<>();
            }

            for (ProjectParticipan join : joinList) {
                if (p.getProjectNo().equals(join.getProjectNo())) {
                    boolean isCurrentUserResponsible = postId.contains(join.getPostId().intValue());
                    if (isCurrentUserResponsible) { // 如果当前用户负责该阶段
                        //如果这个参与人的岗位id在配置的id中  并且没有出现在audit中
                        if (!audit.contains(join.getPostId().intValue())) {
                            resultProjectNoList.add(join.getProjectNo()); // 添加项目编号
                        }
                    }
                }
            }
        }

        resultProjectNoList.add("0");//至少加一个 控制sql语句有in
        resultProjectNoList.addAll(adminSet);

        //加一个核算环节待提交的核算的 驳回的
        //必须是我参与的
        LambdaQueryWrapper<ProjectAccounting> accountWrapper = new QueryWrapper<ProjectAccounting>().lambda();
        accountWrapper.in(ProjectAccounting::getAudit, Arrays.asList("1", "3"));
        List<ProjectAccounting> accountingList = accountingService.list(accountWrapper);
        for (ProjectAccounting accounting : accountingList) {
            //是我参与的
            if (resultProjectNoList.contains(accounting.getProjectNo())) {
                resultProjectNoList.add(accounting.getProjectNo());
            }
        }
        query.setProjectList(new ArrayList<>(resultProjectNoList));

        Page<Object> page = PageHelper.startPage(query.getPageNum(), query.getPageSize());
        query.setStatus("1");
        List<Project> list = projectMapper.getList(query);
        System.out.println(page.getTotal());
        for (Project project : list) {
            setOprator(project);
            setCurentPeople(project);
        }
        return new TableDataInfo(list, page.getTotal());
    }


    @Override
    public Map<String, Object> myListProcessing() {
        Map<String, Object> map = new HashMap<>();
        ProjectQuery query = new ProjectQuery();
        Long userId = SecurityUtils.getLoginUser().getUserId();
        query.setUserId(userId);
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            System.out.println("当前用户有admin角色权限");//管理员看全部？
        } else {
            LambdaQueryWrapper<Project> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(Project::getUserId, SecurityUtils.getLoginUser().getUser().getUserId());
            queryWrapper.select(Project::getProjectNo);
            //我发起的
            List<Object> nameObjects = this.baseMapper.selectObjs(queryWrapper);
            //我参与的
            List<String> createProject = new ArrayList<>(nameObjects.stream()
                    .map(obj -> (String) obj)
                    .toList());
            List<String> currentUserJoinProject = participanService.getCurrentUserJoinProject();
            currentUserJoinProject.addAll(createProject);
            currentUserJoinProject.add("0");//至少加一个 控制sql语句有in
            query.setProjectList(currentUserJoinProject);
            List<Project> myJoin = projectMapper.getList(query);
            map.put("myJoin", myJoin);

        }

        // 2. 各阶段项目数量查询
        Map<String, String> phases = Map.of(
                "pre", "2",
                "impl", "3",
                "accept", "4",
                "accounting", "5",
                "warranty", "6",
                "complete", "7"
        );

        phases.forEach((key, phaseId) -> {
            query.setPhaseId(phaseId);
            query.setStatus("1");
            List<Project> projects = projectMapper.getList(query);
            map.put(key, projects != null ? projects.size() : 0);
        });

        return map;

    }

    @Override
    public Map<String, BigDecimal> getAllDetail() {
        Map<String, BigDecimal> map = new HashMap<>();
        //总金额
        BigDecimal totalMoney = BigDecimal.ZERO;
        //已发放
        BigDecimal already = BigDecimal.ZERO;
        //待发放
        BigDecimal wait = BigDecimal.ZERO;
        if (SecurityUtils.hasRole("admin") || SecurityUtils.hasRole("gjadmin")) {
            List<AllocationDetail> detailList = detailService.list();
            for (AllocationDetail detail : detailList) {
                totalMoney = totalMoney.add(detail.getPersonMoney() != null ? detail.getPersonMoney() : BigDecimal.ZERO);
                already = already.add(detail.getAlready() != null ? detail.getAlready() : BigDecimal.ZERO);
            }
            wait = totalMoney.subtract(already);
            map.put("totalMoney", totalMoney);
            map.put("already", already);
            map.put("wait", wait);
        } else {

            //查询自己的总绩效 待发放 已发放
            LambdaQueryWrapper<AllocationDetail> detailWrapper = Wrappers.lambdaQuery();
            detailWrapper.eq(AllocationDetail::getPersonId, SecurityUtils.getUserId());

            List<AllocationDetail> detailList = detailService.list(detailWrapper);
            for (AllocationDetail detail : detailList) {
                totalMoney = totalMoney.add(detail.getPersonMoney() != null ? detail.getPersonMoney() : BigDecimal.ZERO);
                already = already.add(detail.getAlready() != null ? detail.getAlready() : BigDecimal.ZERO);
            }
            wait = totalMoney.subtract(already);
            map.put("totalMoney", totalMoney);
            map.put("already", already);
            map.put("wait", wait);
        }

        return map;
    }

    @Override
    public TableDataInfo warrantyTime(ProjectQuery query) {
        LambdaQueryWrapper<ProjectWarranty> queryWrapper = Wrappers.lambdaQuery();
        ProjectWarranty warranty = new ProjectWarranty();

        List<ProjectWarranty> warrantyList = warrantyService.list(queryWrapper);

// 初始化不同时间段的项目编号集合
        List<String> oneWeekProjects = new ArrayList<>();
        List<String> oneMonthProjects = new ArrayList<>();
        List<String> twoMonthsProjects = new ArrayList<>();
        List<String> threeMonthsProjects = new ArrayList<>();
        List<String> timeoutProjects = new ArrayList<>();

// 当前日期
        LocalDate currentDate = LocalDate.now();

        for (ProjectWarranty item : warrantyList) {
            // 1. 筛选实收金额不等于质保金的记录
            BigDecimal received = item.getReceivedAmount();
            BigDecimal warrantyMoney = item.getWarranty();
            if (received != null && warrantyMoney != null && received.compareTo(warrantyMoney) == 0) {
                continue;
            }

            // 2. 计算质保金到期日
            Date startDate = item.getStartDate();
            Double cycle = item.getCycle();
            if (startDate == null || cycle == null) {
                continue; // 无效数据跳过
            }

            // 转换为Java8日期类型
            LocalDate dueDate = startDate.toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate()
                    .plusMonths(cycle.longValue());

            // 计算剩余天数（可能为负数）
            long daysRemaining = ChronoUnit.DAYS.between(currentDate, dueDate);

            // 3. 根据剩余天数分类
            if (daysRemaining < 0) {
                timeoutProjects.add(item.getProjectNo());
            } else if (daysRemaining <= 7) {
                oneWeekProjects.add(item.getProjectNo());
            } else if (daysRemaining <= 30) {
                oneMonthProjects.add(item.getProjectNo());
            } else if (daysRemaining <= 60) {
                twoMonthsProjects.add(item.getProjectNo());
            } else if (daysRemaining <= 90) {
                threeMonthsProjects.add(item.getProjectNo());
            }
            // 超过90天的记录不处理
        }

        //超时的
        LambdaQueryWrapper<Project> timeoutProjectsWrapper = Wrappers.lambdaQuery();
        timeoutProjectsWrapper.in(timeoutProjects.size() > 0, Project::getProjectNo, timeoutProjects);

        //一周内的
        LambdaQueryWrapper<Project> oneWeekProjectsWrapper = Wrappers.lambdaQuery();
        oneWeekProjectsWrapper.in(oneWeekProjects.size() > 0, Project::getProjectNo, oneWeekProjects);

        //一个月内的
        LambdaQueryWrapper<Project> oneMonthProjectsWrapper = Wrappers.lambdaQuery();
        oneMonthProjectsWrapper.in(oneMonthProjects.size() > 0, Project::getProjectNo, oneMonthProjects);


        return null;
    }

    @Override
    public List<String> getMessage(ProjectQuery query) {
        //获取阶段
        int stage = query.getStage();
        String projectNo = query.getProjectNo();
        if (StringUtils.isEmpty(projectNo)) {
            return new ArrayList<>();
        }
        //获取角色
        Long userId = SecurityUtils.getUserId();
        LambdaQueryWrapper<ProjectParticipan> joinQuery = Wrappers.lambdaQuery();
        joinQuery.eq(ProjectParticipan::getProjectNo, projectNo);
        joinQuery.eq(ProjectParticipan::getParticipantId, userId);
        joinQuery.in(ProjectParticipan::getPostId, Arrays.asList(2, 5, 16, 18));//销售负责人 项目经理 工程施工 技术施工

        List<ProjectParticipan> personList = participanService.list(joinQuery);
        //不属于销售负责人 项目经理 工程施工 技术施工
        if (personList == null || personList.size() == 0) {
            return new ArrayList<>();
        }

// 查询已上传的附件类型
        LambdaQueryWrapper<ProjectAttachment> attachmentWrapper = Wrappers.lambdaQuery();
        attachmentWrapper.eq(ProjectAttachment::getProjectNo, projectNo);
        attachmentWrapper.select(ProjectAttachment::getAttachmentType);

        List<ProjectAttachment> attachments = fileService.list(attachmentWrapper);

// 提取 attachmentType 并转换为 Integer 类型的 Set
        Set<Integer> uploadedMaterials = attachments.stream()
                .map(ProjectAttachment::getAttachmentType)
                .filter(Objects::nonNull)
                .map(Integer::valueOf) // 将 String 转为 Integer
                .collect(Collectors.toSet());

        List<Material> allStageMaterials = ProjectDocumentRules.getAllowedMaterials(stage);
        return allStageMaterials.stream()
                .filter(material -> !uploadedMaterials.contains(material.getCode()))
                .map(Material::getName) // 只取名称
                .collect(Collectors.toList());
    }


    @Override
    public void createPay(String projectNo) {

        //进入立项前期  验收 阶段自动查询生成付款信息
        Project projectInfo = projectService.getById(projectNo);
        String housekeeperProject = projectInfo.getHousekeeperProject();

        //查询出库信息 开发票的
        List<ProjectSale> saleList = saleService.list(new LambdaQueryWrapper<ProjectSale>()
                .eq(ProjectSale::getHousekeeperProject, housekeeperProject)
                .eq(ProjectSale::getGoodsId, "00021")//开票的
                .orderByAsc(ProjectSale::getSaleDate));


        ProjectFeeQuery projectFeeQuery = new ProjectFeeQuery();
        projectFeeQuery.setHousekeeperProject(housekeeperProject);
        //所有的收款和付款
        List<ProjectFee> feeList = feeService.getReceiveAndPay(projectFeeQuery);

        //所有的已添加的支付信息
        ProjectPayQuery payQuery = new ProjectPayQuery();
        payQuery.setProjectNo(projectNo);
        List<ProjectPay> payList = payService.getList(payQuery);
//        payService.deleteByProjectNo(projectNo);
        //使用金额total 收款时间 备注 如果都匹配上说明是已经生成的  匹配不上就插入
        BigDecimal totalAdd = BigDecimal.ZERO;
        for (ProjectFee fee : feeList) {
            BigDecimal feeTotal = fee.getTotal();
            totalAdd = totalAdd.add(feeTotal);
            Date feeDate = fee.getSubmitDate();
            String feeRemark = fee.getRemark();
            // 标记是否找到匹配的支付记录
            boolean foundMatch = false;
            for (ProjectPay pay : payList) {
                BigDecimal payTotal = pay.getReceivedAmount();
                Date payDate = pay.getPayDate();
                String payRemark = pay.getRemark();

                // 使用安全比较方式（处理null和精度问题）
                boolean amountMatches = feeTotal != null && payTotal != null && feeTotal.compareTo(payTotal) == 0;
                boolean dateMatches = feeDate != null && payDate != null && feeDate.equals(payDate);
                boolean remarkMatches = Objects.equals(feeRemark, payRemark);

                // 如果发现完全匹配的记录
                if (amountMatches && dateMatches && remarkMatches) {
                    foundMatch = true;
                    break; // 找到匹配项，无需继续检查
                }
            }

            // 没有找到匹配项时才创建新记录
            if (!foundMatch) {
                //查询开票信息
                //1.用totalAdd去消耗sale中的开票金额
                BigDecimal saleInvoice = BigDecimal.ZERO;
                StringJoiner payNo = new StringJoiner(",");
                Date myDate = null;
                for (ProjectSale sale : saleList) {
                    saleInvoice = saleInvoice.add(sale.getInvoiceAmount() != null ? sale.getInvoiceAmount() : BigDecimal.ZERO);
                    // totalAdd >= saleInvoice 说明金额还在这张发票内
                    if (totalAdd.compareTo(saleInvoice) <= 0) {
                        //查询发票信息
                        String code = sale.getCode();
                        LambdaQueryWrapper<ProjectFfinance> financeWrapper = new QueryWrapper<ProjectFfinance>().lambda()
                                .eq(ProjectFfinance::getCode, code);
                        List<ProjectFfinance> financeList = financeService.list(financeWrapper);
                        for (ProjectFfinance finance : financeList) {
                            String financeCode = finance.getFinance();
                            // 使用 lastIndexOf 获取最后一个斜杠的位置
                            int lastIndex = financeCode.lastIndexOf('/');
                            String result = (lastIndex != -1) ? financeCode.substring(lastIndex + 1) : financeCode;

                            if (result != null && !result.isEmpty()) {
                                payNo.add(result);
                            }

                            // 分割字符串并提取日期部分
                            String[] parts = financeCode.split("/");
                            if (parts.length < 1) {
                                throw new IllegalArgumentException("输入字符串不包含斜杠");
                            }
                            String datePart = parts[0]; // 获取 "25.10.12"

                            try {
                                // 创建自定义格式化器，明确指定年份为20xx
                                DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                        .appendPattern("yy.MM.dd")
                                        // 直接计算四位年份：假设 "25" 代表 2025
                                        .parseDefaulting(ChronoField.YEAR_OF_ERA, 2000 + Integer.parseInt(datePart.substring(0, 2)))
                                        .toFormatter();

                                // 解析日期
                                LocalDate date = LocalDate.parse(datePart, formatter);
                                System.out.println("解析后的日期: " + date); // 输出: 2025-10-12
                                // 转换LocalDate到Date
                                myDate = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
                            } catch (DateTimeParseException e) {
                                System.err.println("日期格式错误: " + e.getMessage());
                            } catch (NumberFormatException e) {
                                System.err.println("年份解析失败: " + e.getMessage());
                            }

                        }
                        break;
                    }
                }

                ProjectPay projectPay = new ProjectPay();
                projectPay.setProjectNo(projectNo);
                projectPay.setPayDate(feeDate);
                projectPay.setReceivedAmount(feeTotal);
                projectPay.setRemark(feeRemark);
                if (feeTotal.compareTo(BigDecimal.ZERO) >= 0) {//收款才设置发票编号
                    projectPay.setPayNo(payNo.toString());
                }
                projectPay.setFinanceDate(myDate);
                //付款公司
                projectPay.setCompany(projectInfo.getCustomerName());
                //合同金额
                projectPay.setTotalAmount(projectInfo.getContractAmount());

                //使用合同金额contractAmount 和财务实收feeTotal  计算财务实收百分比 保留两位小数
                // 假设 contractAmount 和 feeTotal 已定义
                BigDecimal contractAmount = projectInfo.getContractAmount();

// 判断合同金额是否为空或零，防止除以零异常
                if (contractAmount == null || contractAmount.compareTo(BigDecimal.ZERO) <= 0) {
                    // 合同金额无效时的默认处理，比如返回 0%
//                    projectPay.setPercentage();
                } else {
                    // 计算百分比： (feeTotal / contractAmount) * 100
                    double percentDouble = feeTotal.divide(contractAmount, 4, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100"))
                            .doubleValue();
                    projectPay.setReceivedPercentage(percentDouble);
                }

                //设置付款百分比

                payService.save(projectPay);
            }
        }
    }

    @Override
    public String findMaxCodeByPrefix(String prefix) {
        return projectMapper.findMaxCodeByPrefix(prefix);
    }

    @Override
    public ProjectResult getResultInfoById(String id) {
        ProjectResult projectResult = new ProjectResult();//返回信息
        Project project = this.getById(id);
        projectResult.setProject(project);
        projectResult.setCreateTime(project.getCreateTime());
        projectResult.setEndTime(new Date());
        ProjectParticipanQuery participanQuery = new ProjectParticipanQuery();
        participanQuery.setProjectNo(id);

        //有多少人参与了绩效分配
        LambdaQueryWrapper<AllocationDetail> aalocationWrapper = new QueryWrapper<AllocationDetail>().lambda()
                .eq(AllocationDetail::getProjectNo, id);
        List<AllocationDetail> personList = allocationDetailService.list(aalocationWrapper);
        // 统计不同 personId 的数量
        long personCount = personList.stream()
                .map(AllocationDetail::getPersonId)
                .distinct()
                .count();

        projectResult.setAllocationPerson(Integer.parseInt(String.valueOf(personCount)));
        //参与人信息
        List<ProjectParticipan> participanList = participanService.getList(participanQuery);
        projectResult.setParticipanList(participanList);
        //附件信息
        ProjectFileQuery fileQuery = new ProjectFileQuery();
        fileQuery.setProjectNo(id);
        List<ProjectAttachment> fileList = fileService.getList(fileQuery);
        projectResult.setFileList(fileList);

        //付款信息
        ProjectPayQuery projectPayQuery = new ProjectPayQuery();
        projectPayQuery.setProjectNo(id);
        List<ProjectPay> payList = payService.getList(projectPayQuery);
        projectResult.setPayList(payList);

        //实施日志信息
        ProjectImplementQuery projectImplementQuery = new ProjectImplementQuery();
        projectImplementQuery.setProjectNo(id);
        List<ProjectImplement> implementList = implementService.getList(projectImplementQuery);
        projectResult.setImplementList(implementList);

        //核算信息
        ProjectAccountingQuery projectAccountingQuery = new ProjectAccountingQuery();
        projectAccountingQuery.setProjectNo(id);
        List<ProjectAccounting> accountingList = accountingService.getList(projectAccountingQuery);
        projectResult.setAccountingList(accountingList);

        //累加项目税额 taxAmount   项目材料成本 materialCost
        //报销费用 costOne 其他成本二 costTwo 其他成本三 costThree
        //人工成本

        //总成本
        BigDecimal cost = BigDecimal.ZERO;
        //毛利润
        BigDecimal profit = BigDecimal.ZERO;
        //成本税费
        BigDecimal costFees = BigDecimal.ZERO;
        //差额税费
        BigDecimal differenceFees = BigDecimal.ZERO;
        //税前利润
        BigDecimal beforeProfit = BigDecimal.ZERO;
        //纯利润扣质保金
        BigDecimal afterProfit = BigDecimal.ZERO;
        //项目税额
        BigDecimal taxAmount = BigDecimal.ZERO;

        for (ProjectAccounting accounting : accountingList) {
            cost = cost.add(accounting.getCostOne() != null ? accounting.getCostOne() : BigDecimal.ZERO).add(accounting.getCostTwo() != null ? accounting.getCostTwo() : BigDecimal.ZERO)
                    .add(accounting.getCostThree() != null ? accounting.getCostThree() : BigDecimal.ZERO).add(accounting.getMaterialCost() != null ? accounting.getMaterialCost() : BigDecimal.ZERO)
                    .add(accounting.getFundCost() != null ? accounting.getFundCost() : BigDecimal.ZERO).add(accounting.getLaborCost() != null ? accounting.getLaborCost() : BigDecimal.ZERO);
            profit = profit.add(accounting.getProfit() != null ? accounting.getProfit() : BigDecimal.ZERO);

            costFees = costFees.add(accounting.getCostFees() != null ? accounting.getCostFees() : BigDecimal.ZERO);

            differenceFees = differenceFees.add(accounting.getDifferenceFees() != null ? accounting.getDifferenceFees() : BigDecimal.ZERO);

            beforeProfit = beforeProfit.add(accounting.getBeforeProfit() != null ? accounting.getBeforeProfit() : BigDecimal.ZERO);

            afterProfit = afterProfit.add(accounting.getAfterProfit() != null ? accounting.getAfterProfit() : BigDecimal.ZERO);

            taxAmount = taxAmount.add(accounting.getTaxAmount() != null ? accounting.getTaxAmount() : BigDecimal.ZERO);

        }
        projectResult.setCost(cost);
        projectResult.setProfit(profit);
        projectResult.setDifferenceFees(differenceFees);
        projectResult.setBeforeProfit(beforeProfit);
        projectResult.setAfterProfit(afterProfit);
        projectResult.setTaxAmount(taxAmount);
        projectResult.setCostFees(costFees);

        //质保信息
        ProjectWarrantyQuery projectWarrantyQuery = new ProjectWarrantyQuery();
        projectWarrantyQuery.setProjectNo(id);
        List<ProjectWarranty> warrantyList = warrantyService.getList(projectWarrantyQuery);
        projectResult.setWarrantyList(warrantyList);

        //环节信息
        ProjectPhaseQuery projectPhaseQuery = new ProjectPhaseQuery();
        projectPhaseQuery.setProjectNo(id);
        List<ProjectPhase> phaseList = phaseService.getList(projectPhaseQuery);
        projectResult.setPhaseList(phaseList);


        //计算相隔天数
        // 计算时间差
        Instant createInstant = projectResult.getCreateTime().toInstant();
        Instant endInstant = projectResult.getEndTime().toInstant();

        // 计算相差的天数
        long daysBetween = Duration.between(createInstant, endInstant).toDays();
        projectResult.setDays((int) daysBetween);
        System.out.println("相隔天数: " + daysBetween);


        //财务实收金额
        String housekeeperProject = project.getHousekeeperProject();
        //所有的收款
        ProjectFeeQuery projectFeeQuery = new ProjectFeeQuery();
        projectFeeQuery.setHousekeeperProject(housekeeperProject);
        List<ProjectFee> feeList = feeService.getReceiveFee(projectFeeQuery);
        BigDecimal feeTotal = BigDecimal.ZERO;
        for (ProjectFee fee : feeList) {
            feeTotal = feeTotal.add(fee.getTotal() != null ? fee.getTotal() : BigDecimal.ZERO);
        }
        projectResult.setReceiveAmount(feeTotal);

        //


        return projectResult;
    }


    // 统一前缀映射方法
    private String getPrefixByCompanyType(String companyType) {
        if ("1".equals(companyType)) {
            return HCXX;
        } else if ("2".equals(companyType)) {
            return SDGC;
        } else if ("3".equals(companyType)) {
            return YSZH;
        } else {
            throw new IllegalArgumentException("归属公司类型有误");
        }
    }

    // 修复后的编码生成方法（强制时间同步）
    public String generateCompanyCode(String currentCode, String prefix) {
        if (currentCode == null || currentCode.isEmpty()) {
            return generateInitialCompanyCode(prefix);
        }

        // 提取原年月
        String oldYearMonth = currentCode.substring(prefix.length(), prefix.length() + 6);
        // 获取当前年月
        String currentYearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));

        // 若年月不一致，重置为新年月+0001
        if (!oldYearMonth.equals(currentYearMonth)) {
            return generateInitialCompanyCode(prefix);
        }

        // 递增序列号
        String numberPart = currentCode.substring(prefix.length() + 6);
        int nextNumber = Integer.parseInt(numberPart) + 1;
        String formattedNumber = String.format("%04d", nextNumber);
        return prefix + oldYearMonth + formattedNumber;
    }

    // 初始编码生成
    private String generateInitialCompanyCode(String prefix) {
        String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        return prefix + yearMonth + "0001";
    }


    public void setOprator(Project byId) {
        LambdaQueryWrapper<ProjectWarranty> warrantyWapper = new LambdaQueryWrapper<>();
        warrantyWapper.eq(ProjectWarranty::getProjectNo, byId.getProjectNo());
        List<ProjectWarranty> list = warrantyService.list(warrantyWapper);
        BigDecimal warranty = BigDecimal.ZERO;
        if (list != null && list.size() > 0) {
            warranty = list.get(0).getWarranty();
        }
        byId.setWarranty(warranty);
        //hhhh

        ProjectParticipanQuery participanQuery = new ProjectParticipanQuery();
        participanQuery.setProjectNo(byId.getProjectNo());
        List<ProjectParticipan> participanList = participanService.getList(participanQuery);
        // 获取参与者列表 设置当前操作人(需要点击下一步的人)

        //获取这个项目在哪个阶段
        LambdaQueryWrapper<ProjectPhase> phaseWrapper = new LambdaQueryWrapper<>();
//        phaseWrapper.eq(ProjectPhase::getProjectNo, byId.getProjectNo())
//                .eq(ProjectPhase::getStatus, "1");

        // 假设 phaseWrapper 是一个 QueryWrapper 类型的对象
        phaseWrapper.eq(ProjectPhase::getProjectNo, byId.getProjectNo()) // 确保 projectNo 条件不变
                .orderByDesc(ProjectPhase::getPhaseId) // 按 phaseId 降序排列
                .last("LIMIT 1"); // 只取第一条结果

        try {
            ProjectPhase phase = phaseService.getOne(phaseWrapper);
            PhaseDictionary config = phaseDictionaryService.getById(phase.getPhaseId());
            List<Integer> operatorId = config.getOperatorId();
            List<Integer> postId = config.getPostId();
            String joinPeople = "";
            if (operatorId != null && operatorId.size() > 0) {
                //核算环节 有可能吴总并不参与这些项目 需要特殊处理
                if (operatorId.contains(100)) {
                    SysUser sysUser = userService.selectUserById(100L);
                    joinPeople = joinPeople + sysUser.getNickName() + "、";
                }
                for (Integer operatorId1 : operatorId) {
                    for (ProjectParticipan join : participanList) {//如果岗位id匹配上了 获取该操作人
                        if (String.valueOf(join.getPostId()).equals(String.valueOf(operatorId1))) {
                            joinPeople = joinPeople + join.getParticipanName() + "、";
                        }
                    }
                }
            } else {
                for (Integer operatorId1 : postId) {
                    for (ProjectParticipan join : participanList) {//如果岗位id匹配上了 获取该操作人
                        if (String.valueOf(join.getPostId()).equals(String.valueOf(operatorId1))) {
                            joinPeople = joinPeople + join.getParticipanName() + "、";
                        }
                    }
                }
            }
            // 去掉最后一个符号
            if (joinPeople.endsWith("、")) {
                joinPeople = joinPeople.substring(0, joinPeople.length() - 1);
            }

            if (StringUtils.isEmpty(joinPeople) && byId.getPhaseId().equals("1")) {
                joinPeople = byId.getCreateUserName();
            }

            byId.setJoinPeople(joinPeople);
            byId.setPhaseRemark(phase.getRemark());
        } catch (RuntimeException e) {
            throw new RuntimeException("后端接口异常");
        }

    }


    public void setCurentPeople(Project byId) {
        ProjectParticipanQuery participanQuery = new ProjectParticipanQuery();
        participanQuery.setProjectNo(byId.getProjectNo());
        List<ProjectParticipan> participanList = participanService.getList(participanQuery);
        // 获取参与者列表 设置当前操作人(需要点击下一步的人)

        //获取这个项目在哪个阶段
        LambdaQueryWrapper<ProjectPhase> phaseWrapper = new LambdaQueryWrapper<>();
//        phaseWrapper.eq(ProjectPhase::getProjectNo, byId.getProjectNo())
//                .eq(ProjectPhase::getStatus, "1");

        // 假设 phaseWrapper 是一个 QueryWrapper 类型的对象
        phaseWrapper.eq(ProjectPhase::getProjectNo, byId.getProjectNo()) // 确保 projectNo 条件不变
                .orderByDesc(ProjectPhase::getPhaseId) // 按 phaseId 降序排列
                .last("LIMIT 1"); // 只取第一条结果

        try {
            String joinPeople = "";
            ProjectPhase phase = phaseService.getOne(phaseWrapper);
            int phaseId = Integer.parseInt(phase.getPhaseId());
            if (phaseId < 5) {//核算之前的环节 都取所有参与人
                for (ProjectParticipan join : participanList) {//如果岗位id匹配上了 获取该操作人
                    joinPeople = joinPeople + join.getParticipanName() + "、";
                }
            } else {
                PhaseDictionary config = phaseDictionaryService.getById(phase.getPhaseId());
                List<Integer> operatorId = config.getOperatorId();
                List<Integer> postId = config.getPostId();
                if (operatorId != null && operatorId.size() > 0) {
                    //核算环节 有可能吴总并不参与这些项目 需要特殊处理
                    if (operatorId.contains(100)) {
                        SysUser sysUser = userService.selectUserById(100L);
                        joinPeople = joinPeople + sysUser.getNickName() + "、";
                    }
                    for (Integer operatorId1 : operatorId) {
                        for (ProjectParticipan join : participanList) {//如果岗位id匹配上了 获取该操作人
                            if (String.valueOf(join.getPostId()).equals(String.valueOf(operatorId1))) {
                                joinPeople = joinPeople + join.getParticipanName() + "、";
                            }
                        }
                    }
                } else {
                    for (Integer operatorId1 : postId) {
                        for (ProjectParticipan join : participanList) {//如果岗位id匹配上了 获取该操作人
                            if (String.valueOf(join.getPostId()).equals(String.valueOf(operatorId1))) {
                                joinPeople = joinPeople + join.getParticipanName() + "、";
                            }
                        }
                    }
                }
                // 去掉最后一个符号
                if (joinPeople.endsWith("、")) {
                    joinPeople = joinPeople.substring(0, joinPeople.length() - 1);
                }

                if (StringUtils.isEmpty(joinPeople) && byId.getPhaseId().equals("1")) {
                    joinPeople = byId.getCreateUserName();
                }
            }
            byId.setCurrentPeople(joinPeople);
        } catch (RuntimeException e) {
            throw new RuntimeException("后端接口异常");
        }

    }


}
